 Hi, my name is Russell Keith Piggy. I'm here today to show you how you can publish your Python code as an app using briefcase. Little about me, I am from Wajuk Nungabuja, otherwise known as Perth Western Australia. I am a principal engineer in the open source group at Anaconda. They pay for me to attend conferences like this one to talk to people like you. So I'd like to thank them for that support. They also support the Python open source ecosystem more broadly by providing direct financial support to organisations like NumFocus and by employing developers to work full-time on open source projects, projects like Jupyter and Numper. And the open source project that I founded, Beware. For those who haven't come across it before, Beware is not a single product or library or tool. It is a collection of open source tools and libraries for creating native user interfaces in Python, for desktop but also for iOS, for Android and single-page web apps. Each tool in the Beware suite solves one specific part of the overall problem of writing a GUI app in Python and distributing that app to other people on various platforms. Anaconda supports Beware to ensure that Python remains a viable programming language on the platforms that people are increasingly using as part of their day-to-day computing life, phones, tablets and so on. However, it is important to note that Beware is not an Anaconda product or anything like that. It is fully open sourced with independent governance and funding. I just happen to be paid by Anaconda to work on it full-time. Today we are going to look at one of those tools in-depth, Briefcase. Briefcase is a tool for packaging Python applications. It takes your Python code, wraps it up as a standalone unit that you can give to an end user with no Python experience and they can then run or install and run that app on their platform of choice without ever knowing that they are running Python code. Although it uses a pyproject.toml file for configuration, it is not a competitor for setup tools or hatch or flit or poetry for building library wheels. It is not for deploying Django or Flask websites, it is for packaging applications like the ones you would install from an app store or find on your launch pad or start menu. Think things like MS Word, Firefox or Photoshop. It produces an MSI installer on Windows, DMG or raw app bundles for macOS.deb.rpm or package ZST files for app images or flat packs on Linux. It produces iOS and Android projects that can be uploaded directly to the Apple app store or Google Play stores respectively and it produces a zip file you can upload to a static web post for a single page web app. It is also highly extensible so if you wanted to add a snap back end for Linux you could or if you wanted to support an entirely new platform like a set top box or a watch you could do that as well. Briefcase is just as I said one part of the overall Beware suite of tools. While Briefcase is, it does integrate very well with those other tools, it doesn't require the use of those tools. Beware has a GUI toolkit called Toga but you can wrap your Pi side app or Pi game game with Briefcase. Briefcase also isn't a very good match for command line tools at least not yet on every platform. The primary focus of Briefcase at the moment is packaging GUI applications. It can be used for command line apps on Linux. It could potentially be adapted to do that on Windows and Macros but it can't right now. I'd be interested in seeing that use case supported so and I think I know how it can be done as well so if you want to know more come talk to me afterwards or during the questions. The approach used by Briefcase is essentially the dumbest thing that could possibly work for the problem of app distribution. A Briefcase application is a full copy of all your Python code, a full copy of all your code's dependencies and a full copy of a Python interpreter and a stub binary that can be used to start your application. All bundled up in a way that makes sense for the platform that you are supporting. I say it includes an independent Python interpreter, it's probably more accurate to say it ensures a Python interpreter is available. On most platforms that means shipping one but on Linux it can use system packages in some distribution modes. The stub binary is needed so that your application presents as my app.exe rather than Python.exe and to control the runtime Python environment essentially to make sure it doesn't pick up any stray imports from other Python parts but the stub binary is effectively doing exactly the same thing that Python.exe does, it just has all the configuration options filed off and that's pretty much it. Briefcase is mostly a templating tool combined with wrappers around PIP to install your Python dependencies, wrappers around whatever native platform tools are needed to build a DMG or an MSI or whatever else and then sign applications for distribution. Now Briefcase is not the only app packaging tool that exists for Python so why should you use Briefcase and not one of the other options? Well, first off, it doesn't try to be clever. Some alternatives to Briefcase like PyOxidizer or PyInstaller and some modes of operation can involve getting a working app with making an executable and to support the aim of making an executable they play tricks with your code. They bundle it up into a zip archive that's been embedded into the data block of an executable that's unpacked into memory at runtime and that approach can work and when it does work it's great if only because it gives you a single executable that is distributable but it doesn't always work and for a number of reasons, one of which is that a lot of Python code is designed to be run by passing an interpreter over directories of files on disk and that's how Briefcase runs Python and interpreter running over a directory of source code. The only thing Briefcase does is automate the process of getting that working interpreter to an end user in a way that doesn't require the end user knowing anything about Python. Briefcase also cross-platform which means you also have a single configuration file that produces installers for Mac OS, Windows, Linux, iOS, Android and web which means you don't have duplicated configurations for distributing your app, removing a potential source of error. So how do you use Briefcase? Well, the easiest approach is to start a new project from scratch, create a virtual environment, install Briefcase, pip install Briefcase. Briefcase includes a wizard to start a new project. You say Briefcase new, you'll be presented with a list of questions and some explanatory text. You'll be prompted for a formal name, that's the name you show to humans and an app name, sort of a Pythonised version of the name, something you would pip install. You'll be asked for a bundle, let's use for namespacing to separate my hello world from your hello world. It's a common format used by app stores. It's usually a reversed ordering of a domain name that you know. So that bundle is then combined with the app name to make a full bundle ID for your app, so org.beware.hello world. You'll be asked for a project name, a Briefcase project can include multiple distributed apps, you'll be asked for a one line description of your project, author's name and email, that's then used in help text and copyright labels, a URL for your project, a license and lastly a GUI framework. Briefcase provides a template for Toga, which is BeWare's own GUI framework, but there are also templates for PySide, Pursued by Bear, Pygame, or you can select an empty project with no GUI toolkit at all and drop whatever toolkit you want in there. When you complete the wizard, Briefcase will give you instructions how to run your project. And if you look in the hello world folder that's been generated, you'll find a complete stub project including enough code to start an app, application icons in a variety of formats and project metadata. You will get the same files regardless of what GUI format you pick, the only difference will be the contents of app.py, main.py and some of the values in pyproject.toml on the read me and the license file. Pyproject.toml is the configuration file for the project, contents of this file will match the answers that you gave when you set up the wizard. All of the briefcase options are defined in tool.briefcase sections of the and various subsections of that file. The top level project and author identification is in tool.briefcase. And although the template that Briefcase generates with the wizard doesn't include it, Briefcase will also honor all the equivalent PEP 621 metadata keys with the values in tool.briefcase overriding the PEP 621 keys if they've been provided. Individual apps then have their own sections in the file. So this configuration section here tool.briefcase.app.hello world is the configuration for the hello world app inside this project. That's the hello world there is the app name, the formal name of hello world is done just underneath it and then we've got other descriptions there as well. At runtime the configuration for the hello world app is composed out of your project settings overridden by the app settings. So although there isn't an author name listed here in app config, it would inherit one from the project level configuration from the previous slide. If you wanted to have a different author name for this app in your project, you could do so by just adding an author name in the app's configuration block. You'll also notice the icon setting doesn't include a file format extension. That's because Briefcase uses the provided value as a base name and appends the format depending on the platform. So .ico for windows, .png for Linux and so on. On some platforms you actually will need to provide multiple icons in multiple formats, multiple resolutions. Those sizes will be appended to that base name to produce a full name. Now I say that app settings override project settings. There are four exceptions to this behavior. Sources requires test sources and test requires. Sources describes the list of directories of source code that you want to include in your app. So here we're saying everything in the source hello world directory is going to be part of my application. Any code or resources in that folder and its subfolders will be copied into your application bundle. It's a list, so if you specify multiple sources they will all be copied in. The only requirement is that one of your source directories needs to match the name of your app. So hello world in this case. Requires defines the Python requirements for your app. Again, as a list using the same format that you'd used to as an argument to pip install. So a bare package name, a package with a version specifier, a git repository, a path to a local file that contains an installable package, they're all valid options there. Test sources and test requires are essentially the same, but they define code that will only be included when you're running the app in testing mode. These four settings are cumulative settings. So if you specify a sources definition at the project level, any app level sources will be appended to the list that are defined at the project level. So that's you define common requirements at a top level and then application specific requirements as you go. Why does this matter? Well, you can also specify options that are platform specific by adding a configuration section for that platform. The generated PyProject Toml will include a section for all of the supported platforms, Mac OS, Linux, Windows, iOS, Android and web. So what we've got here is the specification for Mac OS. These options will only apply to the Mac OS builds of this app. Sources requires test sources and test requires are cumulative. So any deployment options here will install all the common requirements like NumPy from the previous slide, but will also include Togo Cocoa and Standard NS Log. A Windows deployment will also have NumPy, but won't have Togo Cocoa and Standard NS Log. It'll have Togo WinForms instead. All other settings override app level and project level values. So if you wanted a Mac OS author name, you could drop an author name in there if you wanted. For most platforms, you only need to platform configuration. However, the Linux configuration needs to go a little bit deeper. This is because Briefcase supports multiple packaging formats. There is a Linux section for common settings to all Linux deployments and all Linux packaging, but then there are format specific sections. By default, Briefcase will generate a system package for the Linux distribution you are currently on. So a Debian or a Deb or an RPM. There's a System.Debian and a System.Rail section. You could also add System.Abuntu or System.Fedora sections if you need to define, if you need to generate a package for those platforms. These let you define system specific requirements. Usually system packages that need to exist on your computer to be able to build or use the package. Briefcase also supports app image and flat pack output formats. They have their own configuration options. Now, this stubpriproject.toml file was generated for you by Briefcase Nu, but you don't have to use that wizard. If you've got an existing project, you can roll your own Briefcase configuration into a pyproject.toml by hand. You've just got to put all the keys you need in. The only requirement that Briefcase puts on your code base is that if you are deploying an application called foobar, then you must have a foobar executable module in your code that is your app's entry point. A done domain file in a foobar folder. That's it. What that entry point does is entirely up to you. As long as it's included in your sources definition, Briefcase will try to run it. Alright, so however you've created it, you've now got your Briefcase configuration file. How do we use it? Well, the first thing you want to do is just see if your app runs. Briefcase includes a developer mode which lets you rapidly iterate on your app and its configuration. So if you run briefcase dev, briefcase will use your pyproject.toml to work out how to run your project in your local virtual environment. The first time you do this, it will actually install all your declared dependencies as well. So everything in your requires section will get installed into your local virtual environment. Now, keep in mind the design motivation for Briefcase, Briefcase, the dumbest thing that can possibly work. Briefcase dev is really not much more than shorthand for PIP install for the list of requirements that you've specified, followed by Python minus M hello world with a couple of debug flags turned on. On subsequent runs, the dependency step won't be executed by default. Briefcase will only start the project. It's just to make the startup loop a little bit faster. If you do add or modify dependency, you need to add a dash r flag when you run Briefcase dev. That will force an update of the dependencies as well. And if all you've got is the content generated by the wizard, at this point what you'll get is a working app. It will be an empty window, but it will be a working application. You can now iterate on the code in your app, add features, fix bugs, whatever you need to do, stop the app, add some code, rerun Briefcase dev, the updated app will run. Awesome, we've got ourselves a fast development loop for our application. Eventually, the time will come when we're going to be ready to package our app for distribution. First step, we need to create our app. To do this, Briefcase create. This will do a bunch of things. First, it will look for the platform you are currently on and get an application template for that platform. So I'm running on Mac OS, it will use the Mac OS app template. Secondly, it will obtain a support package. A support package is a version of Python that can be embedded into your app. For Windows, we use the officially supported Python embedded package for every other platform. Beware, sorry, except for Linux, Beware maintains a support package. We use another project's package version on Linux. Whatever your platform, Briefcase will download the support package, unpack it into the application template that was just created. Then Briefcase installs your application code, anything declared in your sources section of your project. It then downloads and installs your app's requirements but it doesn't install them into your local environment. It's installing them into the application template. Because you're building an app for distribution, you can't rely on anything that's in your local environment. It needs to be in the application. Then Briefcase installs any application resources, things like icons. It purges any content that isn't needed. So on Mac OS, for example, we include an XC framework that you don't need at runtime. And then it's done. You've got a complete application template. Your project directory will now have a build folder that contains a platform-specific template for your app. The next step, build your app. Shocking, I know, but it's Briefcase build. What happens in this step varies from platform to platform. On Mac OS, it needs to sign the application bundle so that it can run on device. On Windows, it needs to write some app metadata. On Linux, it needs to compile a stub app. And at this point, there will be a subfolder of the build folder that contains an application along with any other files included as part of the build process. So in this case, again, it's a Mac OS app. If you were to click on that icon, the application would start. Or you can keep a console based and use Briefcase. Run your app with Briefcase Run. And what you should get is a running application. It will be very similar to what you see with Briefcase Dev with a couple of distinct differences. The app will present to the operating system with your formal name. So you'll see Hello World up in the top corner of the screen there rather than saying Python. We'll also have an application icon in the toolbar down the bottom. Little Hello World, it'll be there. Depending on your platform, there may be some other differences as well. The last step is to package your app with Briefcase Package. This does any final packaging that has to be done before distribution, so creating an installer, doing final code signing and so on. Once this command completes, the disk folder in your project will contain an artifact that can be handed to someone for distribution. So a DMG, an MSI, an RPM, a dev, whatever is appropriate for the platform. Some caveats about packaging. At present, we only do automated signing on Mac OS and Windows. On Mac OS, we do full signing and notarization. On Windows, we sign the XE and the MSI file. We've got documentation on how to manage signing for mobile platforms, but the process isn't currently automated. That is something we want to address. Again, if you want to contribute, this is going to be a place you could help. Signing Linux packages is a complete unknown. Patches welcome. The framework is all in place. What we really just need is the specifics of how do you sign an RPM file? How do you specify a signature on RPM file? If you are on Linux and you want to package for another distribution, say to produce a deb file while you're running on Fedora, you can using Docker. Briefcase will manage the entire process of using Docker. You just need to make sure that Docker is installed. So if it is, you can pass in dash dash target with a Docker base image and Briefcase will package an app for that platform. If you're on Mac OS, you can also use that trick to build packages for Linux using Docker. Briefcase package Linux with a dash dash target, it will do exactly the same Docker trick. Spawn up a Docker container and build a Fedora package or a Debian package, whatever. Unfortunately, this doesn't currently work on native Windows. It will under WSL. You also can't build a Mac OS package on Windows or a Windows package on Linux because the tooling to do that is platform specific. CI platforms are your friend here. Okay. So we've packaged our app, we've distributed it to you, distributed it to our users and then you start working on version two. Do you need to go through this whole development process again? Well, you can or you can say Briefcase update. By default, this will reinstall the code for your app if you want to update your requirements as well. You can specify minus R if you want to update all the application resources like icons, you can specify dash dash update resources. Some other features of Briefcase that are worthy of note along the way I've basically been saying Briefcase command as the shorthand in every instance that's actually is a shorthand for Briefcase command platform format. So Briefcase will identify what platform it is running on and pick a default format for that platform. So most platforms have alternative format so you can target an Xcode project rather than a Mac OS app or a Visual Studio project rather than a Windows app or an Athymedial flat pack on Linux. Briefcase create Linux flat pack will create a Linux flat pack. Briefcase also implies earlier steps if they're needed. If you have a fresh project run straight out of Briefcase new and you invoke Briefcase run Briefcase will detect there isn't a template yet so I'd better create it. I haven't built it yet so I'd better build it and then it will run it. Briefcase run also allows for a dash U option which will update the application before execution so your development cycle could just be running Briefcase run dash U over and over and over again. Briefcase will also open your project if it's a simple project like a Mac OS app that's really just telling the file manager to open a folder if it's an IDE batch project it will open the IDE on the project that is generated if it's a Docker build it'll open a shell session on the Docker container that was used to build the app. All right so that's desktop deployment what about deploying to mobile platforms well the steps are essentially the same just add iOS or Android to all the commands Briefcase create iOS Briefcase build iOS and so on similarly for Android Briefcase run Android iOS builds only work on Mac OS but that's because of the underlying tooling requirements Xcode is only available on Mac OS so we're limited there Android builds though will work on Mac OS Linux or Windows when you run Briefcase run iOS Briefcase will ask where do you want to run this code it will look for simulators that are on your system and provide a list to choose from and if you want to shortcut that question you can specify minus D give it a device ID or a device description like an iPhone 14 running iOS 16.4 if there's any ambiguity because you've got multiple iPhone 14 simulators you'll be asked to resolve the discrepancy on Android you'll be asked to walk through the process of creating a new emulator image if you haven't previously created one but once you've picked a device you'll see something like that iOS can currently on the target simulators Briefcase will manage the process of starting the simulator launching the app in the simulator tailing the logs so that you can see the app run you can deploy to physical devices but you need to use Briefcase open to open the Xcode project and then run it through Xcode because there's a bunch of signing things that need to happen that we haven't yet automated on Android you can target emulators or attached devices you need to do a little bit of a dance with the physical device to put it into developer mode and press the settings button seven times in a row and a bunch of weird stuff Briefcase will try to glide you through that process and then point you at docs if it doesn't seem to be working One last deployment target the web if you add web to the end of the commands we've run so far what you'll get is a Briefcase will start a local web server open a browser and you'll see your app rendered as a single page web app all the app logic is executing in the browser so it's not server side it's using PyScript to embed a full python interpreter in your browser and your app's code is running in the browser so Toga B-Wears GUI toolkit includes a web backend this is the Toga backend that needs the most work if you have web skills and you want a way to contribute and you're here for the sprints this is absolutely a place you could help so far we have been writing code using Briefcase dev to check the code works as we expect and Briefcase to run and execute that app as a package bundle if you're building an app for real you're probably going to need to test it your app will have business logic if you want to really want to run the tests of that logic in the environment that is as close to production as possible so if you're developing a mobile app you kind of want to run those tests on a phone so you can verify everything's going to run as you expect so Briefcase supports running in test mode both developed mode and packaged apps can be run in test mode so you can run a test suite on a mobile device simulator the stub app that's generated by Briefcase dev contains a PyTest test suite with a dummy test you just need to extend that test to test suite to validate whatever your app's code is doing the test command returns success or failure at the shell level so you can integrate that into CI processes or part of a PR acceptance release process okay so some common questions and problems the most single most common question in the Briefcase support channel my app runs fine under dev mode but doesn't under run this is because your dev app runs in your local virtual environment run is a standalone environment if you have manually pip installed something locally in your virtual environment it will not be available to your packaged app you need to add an explicit declaration of that requirement in the requires list of your app and then you need to call update minus R to make sure it's installed into your packaged app another common problem Briefcase is only as good as its underlying tools for example Android emulation and Docker both have very specific hardware requirements if your laptop doesn't support those requirements you're not going to be able to run an Android project or build with Docker Briefcase does what it can to identify some of those common modes of failure but it's not perfect sometimes you're going to get back an obscure error coming from Docker and you're just going to have to find out what's causing Docker to do that and it's likely something like hacksome integration which is a CPU hardware level thing Briefcase also can't magically invent platform support that doesn't exist Toga runs on all the platforms that Briefcase supports but it's currently the only toolkit that does you can't use Briefcase to produce an iOS game with Pygame because Pygame doesn't support iOS Qt apparently works with iOS and Android but Pyside the Qt bindings doesn't Kivi is an interesting case here it should in theory be possible to deploy a Kivi app with Briefcase but mobile deployment is a bit of a complicated beast and so that doesn't work out of the box right now we would very much like to support Kivi so if you know anything about Kivi and you are interested in Kivi support come have a chat because absolutely want to be able to do that What about third-party code? Well if the package you're looking for is pure Python and it's on PyPI you can just use it put it in your requires list and be done with it the only place that will fall down is if you've got sys.platform equals logic in it in which case you might need to submit a patch to actually get that code to support iOS or Android Anything with binary modules that's a little bit more complicated on desktop binary wheels just work they're pip installed they're distributed without any difficulty on mobile binary wheels just work too but most packages don't publish binary wheels for iOS and Android in fact Beware is currently the only group we're aware of that's publishing by or even building binary wheels for iOS and Android we maintain independent pip compatible repositories where those but wheels are stored if the package you need is on that supported list you're fine if it isn't building them is complicated this is one of the big items on out to do list for the coming year in the meantime NumPy, Pandas, Pillow, old versions of cryptography and about 40 other popular packages have binary wheels unfortunately, PsiPy and OpenCV are two common packages that don't run on iOS at least for now we still need to find we need to find a Fortran compiler that will work for iOS Briefcase isn't a feature complete tool by any stretch it works well but there are a lot of places where it could be enhanced or improved I've already flagged some of the obvious performance or potential improvements supporting new platforms like setup boxes and smartwatches new packaging formats like Snap on Linux adding those features actually isn't that much work it requires a little bit of expertise or research on how to drive the packaging tools on those platforms but if it can be done as an external plug-in registering against entry points that Briefcase provides I'd like to be able to provide an answer for command line apps as I said before I think I know how it can be done just need to do the work permissions are also a big item on our wish list this is the most significant on mobile where you need to ask for specific permissions to access the camera or access geolocation services these permissions are becoming increasingly common on desktop as well I expect this will be coming sooner rather than later just purely because you've kind of got to have them we'd also like to get iOS and mobile to tier 3 support in CPython Core and eventually have CPython distribute the support packages that Beware is currently maintaining part of this effort will be making the cross-platform builds with a pet 517 interface something that's officially supported we're going to be starting work on this sort of in a month or two lastly at publication Briefcase currently stops the process of packaging your app however app stores all have APIs to support automated publications so potentially Briefcase could manage that process too and that's Briefcase if you do nothing else I recommend going through the Beware tutorial docs.beware.org everything I've spoken about today is part of Briefcase there are plenty of configuration options that I haven't gone through if you want to know more Briefcase's documentation is very thorough if you haven't got I haven't got any detail on Toga Toga's docs aren't as complete as Briefcase but they're getting a lot better and the latest build on Read the Docs is getting reasonably feature complete but there is also a separate Toga tutorial plus a lot of sample code and projects in the Toga GitHub repo if you like what you've seen here and you'd like to support this work on Briefcase and the Beware project you can join the project as a financial member you can also back me on GitHub sponsors the income we raise is used to cover stickers and hosting and things like that like I said earlier I am paid to work by an account to work on Beware but the project itself is independently managed and funded so that financial support is important we've also got a discord plus discussion forums ticket trackers for all the projects details on Beware.org or if working kind is more your thing we're always looking for new contributors we have a long list of features we'd like to add we have challenge coins for people who contribute I will be here for the full sprints we've got a list of issues for first-time contributors and there's still plenty of low-hanging fruits even if you're inexperienced as a Python developer Thank you so much Russell there are some questions that we have here up front this project seems to do everything is there anything that's out of scope or is it just like you want to do everything and be everything no okay so space lasers to destroy the moon no not going to do that the but like if I have space lasers you can bundle it for iOS well yeah so the the key thing is that it looks like it does a lot it's actually not most of the stuff that's actually doing is other tools all we've done is put a wrap around the outside of it so that I don't have to teach a Python programmer who's just done you know a Django Girls tutorial or something like that how to drive Xcode configuration options to get a big get code on their phone under the hood you can actually like you put it put a briefcase into verbose mode turn on dash dash vv it will show you the command line stuff that it's running and it's just command line execution of a bunch of system tools with all of that detail to kind of abstract it away and made common into a configuration file format rather than spewing you know all the all the stuff that an Xcode build will throw at you or Android build or anything else so it's it's trying to make the process of getting code onto actual devices easy by wrapping the tools that already exist in a nicer interface thank you we have time for one more question Emma please in the back hello so I will try to keep this short it's so you talk about different distribution windows Linux you didn't talk about cross processor architecture like ARM versus i86 and as a sub question I run termics on Android so could I take some of the packages from beware that don't combine natively and use them in termics that would be an interesting for the android would be an interesting one probably not I would need to look a little bit deeper the in terms of CPU architecture support for desktop platforms it's basically x86 on all of those platforms we do both like a universal two fat builds for M1 and x86 on macOS on device we are looking to target a native android application it builds i386 x86 64 ARM 32 ARM 32 eABI and ARM 64 what that means for the native packages on Android good question I'm not sure I'd have to look thank you thank you so much Russell