The --no-unsign flag was disabling relocatable-python's own
fix_broken_signatures step (locallibs/fix.py), which ad-hoc re-signs
every binary modified by install_name_tool before ensurepip runs.
That's the exact code path needed to satisfy Apple Silicon Gatekeeper.
The flag's stated purpose ('don't touch the python.org signature') was
never achievable — install_name_tool invalidates the signature whether
you tell relocatable-python to handle it or not. Keeping --no-unsign
just left the binary in a broken signed state, which Gatekeeper SIGKILLs.
Bumping RP_SHA to 8ee72fe simultaneously, since the prior pin
(fb4dd9b) had the same code path and was only kept while investigating.
The newer SHA additionally sets CPPFLAGS for pip, useful for packages
with native extensions.
Closes the local equivalent of gregneagle/relocatable-python#32 for our
build pipeline.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
python
A Python 3 framework that installs to /Library/ManagedFrameworks/Python/Python3.framework.
Please see Apple's documentation on file system basics for context.
This is an intended replacement for /usr/bin/python, which Apple removed in macOS 12.3 (Spring 2022).
Apple Silicon Only
Builds and packages target Apple Silicon (arm64). Universal2 outputs are no longer produced. Build hosts and target machines must be Apple Silicon Macs.
Why use this instead of a package from python.org?
- Ships with PyObjC and other modules useful for Mac admins, similar in spirit to the Apple Python it replaces
- Installs to a location less likely to be overwritten, removed, or modified by other Python installations
Using interactively
After installing the package, /usr/local/bin/managed_python3 is a symlink to /Library/ManagedFrameworks/Python/Python3.framework/Versions/Current/Resources/Python.app/Contents/MacOS/Python.
Using with scripts
Point your shebang directly at the symlink:
#!/Library/ManagedFrameworks/Python/Python3.framework/Versions/Current/bin/python3
print('This is an example script.')
zshenv global alias
For zsh scripts you can add a global alias to /etc/zshenv:
alias -g python3.framework='/Library/ManagedFrameworks/Python/Python3.framework/Versions/Current/bin/python3'
See Armin Briegel's "Moving to Zsh" Part II and IV.
Notes
Only a single package may be installed at any given time. The preinstall script removes any previous framework.
Upgrades
Python itself has its own release cadence; this package will see additional updates as 3rd-party libraries release fixes and security updates. Always test your scripts before deploying broadly.
Downgrades
Not supported.
pip
pip is bundled but not recommended for installing external libraries into the framework. Use a virtual environment or a tool like pyenv instead. Pull requests to the recommended requirements file are welcome.
Building locally
Build an unsigned framework on Apple Silicon with:
./build_python_framework_pkgs.zsh --python-version 3.13.13
Pass --installer-id, --application-id, and --notary-password to produce a signed and notarized .pkg.
Updating packages
Do this in a clean virtual environment. After every Python package install, run pip freeze | xargs pip uninstall -y to reset the environment.
CI Job
To update the signing certificate, run base64 -i /path/to/certificate.p12 -o base64string and import it into the GitHub Actions secrets store along with the matching password.
Credits
Built on two open-source tools by Greg Neagle: