PyWinGUI GUI Automation Library for Windows Forms (Binary Distribution)
Project description
build_tools — README
This document explains how to build, test, and publish Windows Nuitka-compiled wheels for the pywingui project using the repository's build scripts and GitHub Actions.
Checklist
- Create PyPI API token and add it to GitHub Secrets (
PYPI_API_TOKEN). - Verify
make_nuitka_wheel.ps1andpush.ps1are configured correctly. - Test a local build for each target Python interpreter (32-bit and 64-bit).
- (Optional) Run the GitHub Actions workflow manually to inspect artifacts.
- Tag and push when ready to publish to PyPI (workflow will run and upload wheels).
Overview
make_nuitka_wheel.ps1— Builds a wheel for a specific Python interpreter using Nuitka. It compiles selected modules into extension modules and packages them into a wheel.push.ps1— Uploads the built wheel(s) to PyPI usingtwine, reading the token from environment variables (PYPI_API_TOKENorTWINE_PASSWORD).- GitHub Actions workflow (
.github/workflows/build-windows-wheels.yml) — Builds Windows wheels across a matrix of Python versions and architectures (x86/x64) and publishes them to PyPI when a tag is pushed andPYPI_API_TOKENis set as a secret.
Security model
- For releasing protected/compiled code, build and publish per-ABI wheels (win32 and win_amd64) and do not include source fallback files in release wheels. To do that, run the build script without the
-IncludeSourceFallbacksswitch. - If you need debug/compatibility builds that include Python source fallbacks, run the build script with
-IncludeSourceFallbacks. Do not publish fallback-enabled wheels to PyPI if you want to protect source code.
Local usage
- Build a secure wheel (no source fallbacks)
Open PowerShell in the repository root and run:
# Build for a target Python interpreter (replace path with target python.exe)
.\build_tools\make_nuitka_wheel.ps1 -PythonExe "C:\Path\To\Target\python.exe"
- Build a compatibility/debug wheel (includes
_source.pyfallbacks)
# Include source fallbacks for debugging (not recommended for protected releases)
.\build_tools\make_nuitka_wheel.ps1 -PythonExe "C:\Path\To\Target\python.exe" -IncludeSourceFallbacks
- Inspect the produced wheel
After the build completes, the wheel(s) are placed under dist\. To list the wheel files:
Get-ChildItem .\dist\*.whl | Sort-Object LastWriteTime -Descending | Format-Table Name,FullName -AutoSize
To list the contents of a wheel (using Python):
python - <<'PY'
import zipfile
w = r".\dist\your-built-wheel.whl" # replace with the actual file
z = zipfile.ZipFile(w)
print('\n'.join(z.namelist()))
PY
- Test install in a fresh venv (use the same interpreter you built for)
"C:\Path\To\Target\python.exe" -m venv .\test_env
.\test_env\Scripts\python.exe -m pip install --upgrade pip
.\test_env\Scripts\python.exe -m pip install .\dist\your-built-wheel.whl
.\test_env\Scripts\python.exe -c "import pywingui; import pywingui.controller as controller; print('OK', controller)"
Publishing to PyPI (local)
- Set token in environment (temporary for current PowerShell session):
$env:PYPI_API_TOKEN = 'pypi-<your-token-here>'
# or the less-preferred variable used by older scripts
$env:TWINE_PASSWORD = 'pypi-<your-token-here>'
- Run the push script (it will install twine into the project's venv and upload):
.\build_tools\push.ps1
GitHub Actions (automated build & publish)
What the workflow does
- For each Python version and architecture in the matrix it:
- Checks out the repo
- Sets up Python (x86/x64)
- Installs build dependencies (nuitka, wheel, setuptools)
- Runs
make_nuitka_wheel.ps1to build a wheel - Uploads the built wheel(s) as an artifact for inspection
- If the workflow run is triggered by a pushed tag (e.g.
v1.2.3) andPYPI_API_TOKENis set as a repository secret, the workflow will runtwineto uploaddist/*to PyPI.
One-time setup on GitHub
- Create a PyPI API token at https://pypi.org (Account → API tokens).
- In GitHub, go to the repository: Settings → Secrets and variables → Actions → New repository secret
- Name:
PYPI_API_TOKEN - Value: (the token you copied from PyPI)
- Name:
Triggering a publish
- To test the workflow without publishing, run the workflow manually from Actions → your workflow → Run workflow.
- To publish to PyPI, push a tag. Example:
git add .
git commit -m "release prep"
git tag v1.0.0
git push origin main
git push origin v1.0.0
Versioning
The build scripts set a SMART_VERSION environment variable that setup_build_pkg.py reads and uses as the package version when building a wheel. By default make_nuitka_wheel.ps1 generates a timestamp-based PEP-440-friendly version to keep builds unique (useful for automated builds).
You can control the version in three ways:
- Let the build produce a timestamped version (default)
- This happens automatically when you run
make_nuitka_wheel.ps1without-Version. The script setsSMART_VERSIONto a value like2026.1.2.10.5+2026.01.02.10.05(format keeps it PEP-440 compatible while preserving a raw timestamp suffix).
- Provide an explicit version when running the build script
- Use the
-Versionparameter to set a specific PEP-440 compliant version string. Example:
# Set the build version explicitly
.\build_tools\make_nuitka_wheel.ps1 -PythonExe "C:\Path\To\python.exe" -Version "1.2.3"
- The provided
-Versionvalue overrides the generated timestamp and is exported asSMART_VERSIONfor the wheel build.
- In CI (recommended for releases): use the git tag as the version
- When publishing releases from CI you typically want the wheel version to match the git tag (for example
v1.2.3or1.2.3). You can pass the tag name into the build script by supplying-Versionor by exportingSMART_VERSIONin the runner environment.
Example (GitHub Actions step) — pass the tag name into the build script:
- name: Build wheel (Nuitka)
shell: pwsh
run: |
$py = (Get-Command python).Source
$ver = '${{ github.ref_name }}' # e.g. 'v1.2.3' or '1.2.3'
Write-Host "Building wheel for version: $ver"
.\build_tools\make_nuitka_wheel.ps1 -PythonExe $py -Version $ver
Notes on version format
- Use a PEP-440 compliant version string (for example:
1.2.3,1.2.3.post1,1.2.3rc1). Avoid spaces or characters that are illegal in wheel metadata. - If you use git tags prefixed with
v(v1.2.3) and prefer to drop thev, strip it in CI before passing to-Version(for example trim the leadingvin the script or set-Version ${{ github.ref_name | replace('v','') }}).
How setup_build_pkg.py reads the version
setup_build_pkg.pyusesos.environ.get('SMART_VERSION', '0.0.0')as the packageversion. Themake_nuitka_wheel.ps1script setsSMART_VERSIONbefore invokingsetup_build_pkg.py, so the wheel will carry theSMART_VERSIONvalue.
Troubleshooting
- If you see
0.0.0in the built wheel metadata,SMART_VERSIONwas not set in the environment at package-build time. Confirm you invokedmake_nuitka_wheel.ps1(it setsSMART_VERSION) and thatsetup_build_pkg.pyis executed in the same process/venv context. - If a wheel is already published with an identical version, PyPI rejects the upload; ensure you increment the version for each published release.
Notes & troubleshooting
- Make sure you build wheels on Windows for Windows wheels. The GitHub Actions workflow uses
runs-on: windows-latest. - Ensure you build one wheel per ABI. For Windows you typically need both win32 and win_amd64 if you support 32-bit and 64-bit Python users.
- If a user reports "No module named 'pywinGUI.controller'" after installing from PyPI:
- Ask them to run
python -c "import platform,sys; print(sys.executable, platform.python_version(), platform.architecture())"andpython -m pip show -f pywinGUI. - Verify they installed the wheel matching their Python bitness. If not, provide the correct wheel or publish both ABI wheels.
- If the installed package has an incorrectly named file (e.g.
_init_.py), remove the package folder and reinstall.
- Ask them to run
CI considerations
- If Nuitka or compiled code requires MSVC or other build tools on the runner, add the installation steps in the workflow (Chocolatey or Visual Studio Build Tools) before running the build script.
- The workflow currently publishes only on tag pushes. You can adjust it to publish on a release or add manual approvals.
Contact
- If a build fails or a wheel raises import errors on a target interpreter, collect the following and open an issue:
- The wheel filename
- The output of
python -c "import platform,sys; print(sys.executable, platform.python_version(), platform.architecture())"on the failing machine - The output of
python -m pip show -f pywinGUI - Any traceback from attempting to
import pywinGUI.controller
This README is intentionally minimal and focused on build and release flow. If you want, I can:
- Add a short
RELEASE.mdwith step-by-step release checklist and gating rules. - Create a GitHub Actions job that requires manual approval before upload.
- Add
cibuildwheelusage for cross-platform future support.
Which of these would you like next?
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pywingui-4.2.6-cp313-none-win_amd64.whl.
File metadata
- Download URL: pywingui-4.2.6-cp313-none-win_amd64.whl
- Upload date:
- Size: 617.0 kB
- Tags: CPython 3.13, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8437059f15849ec7644ff99a3f04dc7a35cd705293aadd8b887d5ba4853d62e4
|
|
| MD5 |
b5a448cc2b225f64168fbe0d038ae15b
|
|
| BLAKE2b-256 |
7c467fa58d4018a0b83283dcf87fa884ea69277dfb480cc769e34f4088a363ea
|
File details
Details for the file pywingui-4.2.6-cp313-none-win32.whl.
File metadata
- Download URL: pywingui-4.2.6-cp313-none-win32.whl
- Upload date:
- Size: 525.7 kB
- Tags: CPython 3.13, Windows x86
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6ef09362cf077cb1f9b2d2636ab43042a71cc9383b573cc78e1d4e39d6e9f801
|
|
| MD5 |
a3cab7902890e9209d00c74504b7c495
|
|
| BLAKE2b-256 |
dd52eee2ecf45810aed0639afae4a3b607b00dbb7a8ae082dc83916508066052
|
File details
Details for the file pywingui-4.2.6-cp312-none-win_amd64.whl.
File metadata
- Download URL: pywingui-4.2.6-cp312-none-win_amd64.whl
- Upload date:
- Size: 623.4 kB
- Tags: CPython 3.12, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5215b25a97e0475626766e4233063b8e8fab68cee9f2bfa69471dcd9020822b0
|
|
| MD5 |
2c40f1d39770273ea18842fc0843de12
|
|
| BLAKE2b-256 |
c8d3a6485525da6c440a24c0d574515eb761f14356f96d285689123e901291b0
|
File details
Details for the file pywingui-4.2.6-cp312-none-win32.whl.
File metadata
- Download URL: pywingui-4.2.6-cp312-none-win32.whl
- Upload date:
- Size: 534.8 kB
- Tags: CPython 3.12, Windows x86
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d198dc422f58930fffd30440525c3b7d9b7c861bf89e8585fc0133a0972268ed
|
|
| MD5 |
385003d9977ae3d8054049d1d7108984
|
|
| BLAKE2b-256 |
189eb0839a78a1062265932ebfb7f40fd1b0cd6eb906b088761d149663c38620
|
File details
Details for the file pywingui-4.2.6-cp311-none-win_amd64.whl.
File metadata
- Download URL: pywingui-4.2.6-cp311-none-win_amd64.whl
- Upload date:
- Size: 628.9 kB
- Tags: CPython 3.11, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
37ce780e2be109ad6b007f314b0396b3e2f69b9caee5223692f7e93653b201c1
|
|
| MD5 |
94bcb3fa22f6fbaae404f779d9b2aca7
|
|
| BLAKE2b-256 |
bd7d0d0abccab668d4ed9d585b6b42dc78572ac6cd7bea73185962539ea7a039
|
File details
Details for the file pywingui-4.2.6-cp311-none-win32.whl.
File metadata
- Download URL: pywingui-4.2.6-cp311-none-win32.whl
- Upload date:
- Size: 540.5 kB
- Tags: CPython 3.11, Windows x86
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
884d7559a5a31d60fd954c5f08e5fd34e186da316b90053df3779be6140914af
|
|
| MD5 |
75d20ba28d73ec47f22e677cf206754e
|
|
| BLAKE2b-256 |
50cec7cadda80ae53b54993ea35f84b5892fad69e16bcaac5ea069d6879fb398
|