Skip to content
jkingokPublic

About

No description, website, or topics provided.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Repository files navigation

MyPyStub

This cross-platform app was generated by Briefcase - part of The BeeWare Project. If you want to see more tools like Briefcase, please consider becoming a financial member of BeeWare.

My first application for prototyping with iDevices and Python

This application is only tested on iPhone and iPad. It uses the iOS limited subset of Toga. It is intended to act as a stub to enable you to install an up-to-date Python interpreter to your device for free. (Apple allows any account to become a Developer account for free that can install up to three apps that are re-deployed once every seven days.)

If you compile and deploy this app, it will create a "MyPyStub" folder in your Files app under "On My iPhone" (or "On My iPad").

You may place Python scripts in there. Either place bare scripts, or place modules in folders. Modules should have a pyproject.toml file to nominate any pure-Python dependencies that will attempt to be downloaded from PyPI at runtime.

Only a minimum of packages are preinstalled (if you build this yourself you can pre-install packages by adjusting the Briefcase configuration).

Writing prototypes

The launcher lists your scripts and project folders; tap one to run it. This lets one of your three free app slots hold many Python prototypes. Scripts run as they would with python script.py, so the same file also works on a desktop, or as a standalone app built with Briefcase. Put their start-up code under if __name__ == "__main__":.

Mode When the run ends Example
Plain script (print, input) when the script returns basics/hello_world.py, basics/hello_you.py
Long-running script when its work finishes threads/countdown.py
Main-thread work when the script returns threads/main_thread.py
Arguments and environment variables (set by swiping right for Setup) when the script returns basics/args_and_env.py, basics/show_args.py, basics/show_env.py
Dependencies (PEP 723) installed first, then as above basics/with_dependency.py
Project folder (pyproject.toml) as for its entry point basics/hello_project/
Entry points ([project.scripts], gui-scripts, other groups) as for a script; several open like a folder projects/two_tools/
Taking over the screen with Toga when it hands the screen back takeover/back_button.py, takeover/nested_takeover.py

Swipe left on a row for Info (a folder's README; a script's docstring, dependencies and source; a project's metadata, README, licence and changelog), and right for Setup, which sets its arguments and environment variables, saving as you go. Variables set on the Setup tab's Environment page are inherited by every run. The in-app Help page explains each one (see "How your script is run"), and the examples are in the app's Examples category. Your own modules are reloaded on each run, so edits take effect without restarting the app.

This is purely experimental at this stage but you're welcome to experiment with it!

Development

Desktop development uses uv:

uv sync
uv run pre-commit install

The pre-commit hooks run the same checks as the pull request gate (.github/workflows/pr-gate.yml): ruff check, pyright, and pytest. To run them by hand:

uv run pre-commit run --all-files

Releasing to TestFlight

Builds are shipped by hand from a clone on a Mac with Xcode, Ruby, and Bundler. The Continuous Delivery to TestFlight workflow only runs fastlane ios share and is manual; on a Mac it costs no CI minutes.

bundle install

Export the App Store Connect API key and team details (keep these out of the repository):

  • APP_STORE_CONNECT_KEY_ID
  • APP_STORE_CONNECT_ISSUER_ID
  • APP_STORE_CONNECT_PRIVATE_KEY
  • APP_STORE_TEAM_ID

Then run one of the lanes in fastlane/Fastfile:

bundle exec fastlane ios share
  • share builds and uploads to TestFlight. TestFlight's "What to Test" is the newest build's section of What's New, not the git log.
  • mirror copies main and its release tags to the public repository (bundle exec fastlane mirror; set PUBLIC_REPO_URL to override the remote). share runs it after tagging, so the About page's Source link works in the public repository; run it by hand to catch up after merging.
  • local builds and installs on local devices.
  • manual builds the Xcode project and leaves signing and deploying to Xcode.

The share lane also collects the change fragments in changes/ into the app's Help → What's New page and commits them (see changes/README.md).

Fastlane sets the version, so do not edit it by hand. Before Briefcase runs, it picks today's date and the next build number on TestFlight, and scripts/set_version.py stamps them into pyproject.toml (restored afterwards). Python sees the build number as a fourth number, so the version is plain PEP 440 with no words. Xcode's version keys hold at most three numbers, so it keeps the build number apart. Every lane numbers its build the same way:

Example
Python (app.version, About page) 2026.11.2.3
Xcode CFBundleShortVersionString 2026.11.2
Xcode CFBundleVersion 3

Runs straight from the source tree (briefcase dev, tests) show the placeholder version in pyproject.toml.

After a successful upload, share tags the commit with the Python version (for example 2026.11.2.3) and pushes the tag. The mirror lane copies main and the release tags on main to the public repository, and the About page links to the tag of the running build ("Source"). Tags on commits that aren't on main stay private, so share from main; a build from a branch that is later squash-merged keeps a private tag, and the lane warns about it. Build numbers count both TestFlight and these tags, so a number is never reused.

GitHub Releases

After the tag is mirrored, share creates a GitHub Release for it on the public repository (PUBLIC_REPOSITORY, default jkingok/mypystub). Its title is the version and its body is that build's What's New text, the same Markdown the app shows (scripts/collect_changes.py --release-notes <version>). The About page's Source link opens that Release page, which also leads to the code at the tag.

Creating a Release needs GITHUB_RELEASE_TOKEN, a token allowed to write Releases on the public repository. Keep it in the environment with the App Store Connect keys, never in the repository. (Fastlane's set_github_release takes it as its api_token argument; its own environment variable would be FL_GITHUB_RELEASE_API_TOKEN, but this repository reads GITHUB_RELEASE_TOKEN and passes it in.) Without it share warns and skips the Release, since the upload has already happened; make it later with:

bundle exec fastlane release version:2026.11.8.1

Making a token (desktop or CI)

Use a fine-grained personal access token limited to the public repository:

  1. GitHub → Settings → Developer settings → Personal access tokens → Fine-grained tokens → Generate new token.
  2. Resource owner jkingok; Only select repositories: jkingok/mypystub.
  3. Repository permissions: Contents: Read and write (what creating a Release needs; Metadata read-only is added for you).
  4. Pick an expiry, generate, and copy the token (it is shown once).
  5. On the Mac, export GITHUB_RELEASE_TOKEN=... in the shell profile or keychain-backed secrets, then run the release lane above. In CI, store it as a repository secret.

A classic token with the public_repo scope also works but reaches all your public repositories. Check GitHub's managing personal access tokens page for the current steps; these were written from memory.

About

No description, website, or topics provided.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages