├── tests ├── __init__.py ├── commands │ ├── __init__.py │ ├── base │ │ ├── __init__.py │ │ ├── test_full_kwargs.py │ │ ├── test_properties.py │ │ ├── test_parse_options.py │ │ ├── test_app_module_path.py │ │ └── conftest.py │ ├── build │ │ ├── __init__.py │ │ └── conftest.py │ ├── create │ │ ├── __init__.py │ │ ├── test_cookiecutter_cache_path.py │ │ ├── test_call.py │ │ ├── test_create_app.py │ │ ├── test_install_app_dependencies.py │ │ └── test_install_image.py │ ├── dev │ │ ├── __init__.py │ │ └── conftest.py │ ├── new │ │ ├── __init__.py │ │ ├── test_make_domain.py │ │ ├── test_call.py │ │ ├── test_make_module_name.py │ │ ├── test_is_valid_url.py │ │ ├── test_is_valid_email.py │ │ ├── test_make_class_name.py │ │ ├── test_make_app_name.py │ │ ├── test_make_author_email.py │ │ ├── test_make_project_url.py │ │ ├── conftest.py │ │ ├── test_titlecase.py │ │ ├── test_is_valid_bundle.py │ │ ├── test_is_valid_app_name.py │ │ ├── test_build_app_context.py │ │ ├── test_input_text.py │ │ ├── test_input_select.py │ │ └── test_new_app.py │ ├── run │ │ ├── __init__.py │ │ └── conftest.py │ ├── update │ │ ├── __init__.py │ │ ├── test_call.py │ │ ├── conftest.py │ │ └── test_update_app.py │ └── publish │ │ ├── __init__.py │ │ ├── test_call.py │ │ └── conftest.py ├── config │ ├── __init__.py │ ├── test_GlobalConfig.py │ ├── test_merge_config.py │ └── test_is_pep440_version.py ├── console │ ├── __init__.py │ └── test_select_option.py ├── platforms │ ├── __init__.py │ ├── iOS │ │ ├── __init__.py │ │ └── xcode │ │ │ ├── __init__.py │ │ │ ├── test_mixin.py │ │ │ └── test_build.py │ ├── linux │ │ ├── __init__.py │ │ └── appimage │ │ │ ├── __init__.py │ │ │ ├── test_create.py │ │ │ ├── test_mixin.py │ │ │ └── test_run.py │ ├── macOS │ │ ├── __init__.py │ │ ├── app │ │ │ ├── __init__.py │ │ │ ├── test_mixin.py │ │ │ ├── test_run.py │ │ │ ├── test_package.py │ │ │ └── test_select_identity.py │ │ └── dmg │ │ │ ├── __init__.py │ │ │ └── test_mixin.py │ ├── windows │ │ ├── __init__.py │ │ └── msi │ │ │ ├── __init__.py │ │ │ ├── test_mixin.py │ │ │ ├── test_run.py │ │ │ ├── test_package.py │ │ │ └── test_create.py │ └── conftest.py └── integrations │ ├── __init__.py │ └── xcode │ ├── __init__.py │ ├── security │ ├── no-identities.out │ ├── one-identity.out │ └── multiple-identities.out │ ├── simctl │ ├── no-runtimes.json │ ├── README │ ├── no-devices.json │ ├── single-device.json │ ├── single-device-booted.json │ ├── single-device-unknown.json │ ├── single-device-shutdown.json │ └── single-device-shutting-down.json │ ├── test_get_device_state.py │ ├── test_get_identities.py │ └── test_ensure_xcode_is_installed.py ├── docs ├── spelling_wordlist ├── how-to │ ├── code-signing │ │ ├── macOS.rst │ │ └── index.rst │ ├── PyStackTraceOnXCode.png │ ├── internal │ │ ├── index.rst │ │ └── release.rst │ ├── index.rst │ ├── see_errors_on_ios.rst │ ├── contribute-docs.rst │ └── contribute-code.rst ├── _static │ └── images │ │ └── briefcase.png ├── requirements_docs.txt ├── reference │ ├── platforms │ │ ├── linux │ │ │ ├── index.rst │ │ │ └── appimage.rst │ │ ├── windows │ │ │ ├── index.rst │ │ │ └── msi.rst │ │ ├── index.rst │ │ ├── macOS │ │ │ ├── index.rst │ │ │ ├── app.rst │ │ │ └── dmg.rst │ │ ├── android.rst │ │ └── iOS.rst │ ├── commands │ │ ├── index.rst │ │ ├── new.rst │ │ ├── create.rst │ │ ├── dev.rst │ │ ├── publish.rst │ │ ├── update.rst │ │ ├── package.rst │ │ ├── build.rst │ │ └── run.rst │ └── index.rst ├── background │ ├── index.rst │ ├── success.rst │ ├── faq.rst │ ├── community.rst │ └── releases.rst ├── tutorial │ └── index.rst └── index.rst ├── changes ├── .gitignore ├── 266.feature └── template.rst ├── src └── briefcase │ ├── integrations │ └── __init__.py │ ├── platforms │ ├── android │ │ ├── apk.py │ │ └── __init__.py │ ├── django │ │ ├── app.py │ │ ├── project.py │ │ └── __init__.py │ ├── linux │ │ ├── deb.py │ │ ├── rpm.py │ │ ├── snap.py │ │ ├── flatpak.py │ │ └── __init__.py │ ├── tvOS │ │ ├── xcode.py │ │ └── __init__.py │ ├── wearos │ │ ├── apk.py │ │ └── __init__.py │ ├── macOS │ │ ├── homebrew.py │ │ └── __init__.py │ ├── watchOS │ │ ├── xcode.py │ │ └── __init__.py │ ├── windows │ │ └── __init__.py │ ├── iOS │ │ └── __init__.py │ └── __init__.py │ ├── commands │ ├── __init__.py │ ├── publish.py │ ├── build.py │ ├── package.py │ ├── run.py │ ├── update.py │ └── dev.py │ ├── __init__.py │ ├── __main__.py │ ├── console.py │ └── exceptions.py ├── setup.py ├── .gitignore ├── CONTRIBUTING.md ├── pyproject.toml ├── AUTHORS ├── .github └── workflows │ ├── build_status.yml │ ├── release.yml │ ├── publish.yml │ └── ci.yml ├── MANIFEST.in ├── LICENSE ├── README.rst └── setup.cfg /tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/spelling_wordlist: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/commands/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/config/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/console/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/platforms/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/commands/base/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/commands/build/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/commands/create/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/commands/dev/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/commands/new/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/commands/run/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/commands/update/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/integrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/platforms/iOS/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/platforms/linux/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/platforms/macOS/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /changes/.gitignore: -------------------------------------------------------------------------------- 1 | !.gitignore 2 | -------------------------------------------------------------------------------- /src/briefcase/integrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/commands/publish/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/integrations/xcode/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/platforms/iOS/xcode/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/platforms/macOS/app/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/platforms/macOS/dmg/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/platforms/windows/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/platforms/linux/appimage/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/platforms/windows/msi/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/briefcase/platforms/android/apk.py: -------------------------------------------------------------------------------- 1 | # An implementation would go here! 2 | -------------------------------------------------------------------------------- /src/briefcase/platforms/django/app.py: -------------------------------------------------------------------------------- 1 | # An implementation would go here! 2 | -------------------------------------------------------------------------------- /src/briefcase/platforms/linux/deb.py: -------------------------------------------------------------------------------- 1 | # An implementation would go here! 2 | -------------------------------------------------------------------------------- /src/briefcase/platforms/linux/rpm.py: -------------------------------------------------------------------------------- 1 | # An implementation would go here! 2 | -------------------------------------------------------------------------------- /src/briefcase/platforms/linux/snap.py: -------------------------------------------------------------------------------- 1 | # An implementation would go here! 2 | -------------------------------------------------------------------------------- /src/briefcase/platforms/tvOS/xcode.py: -------------------------------------------------------------------------------- 1 | # An implementation would go here! 2 | -------------------------------------------------------------------------------- /src/briefcase/platforms/wearos/apk.py: -------------------------------------------------------------------------------- 1 | # An implementation would go here! 2 | -------------------------------------------------------------------------------- /docs/how-to/code-signing/macOS.rst: -------------------------------------------------------------------------------- 1 | ===== 2 | macOS 3 | ===== 4 | 5 | **TODO** 6 | -------------------------------------------------------------------------------- /src/briefcase/platforms/android/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | DEFAULT_OUTPUT_FORMAT = 'apk' 3 | -------------------------------------------------------------------------------- /src/briefcase/platforms/django/project.py: -------------------------------------------------------------------------------- 1 | # An implementation would go here! 2 | -------------------------------------------------------------------------------- /src/briefcase/platforms/linux/flatpak.py: -------------------------------------------------------------------------------- 1 | # An implementation would go here! 2 | -------------------------------------------------------------------------------- /src/briefcase/platforms/macOS/homebrew.py: -------------------------------------------------------------------------------- 1 | # An implementation would go here! 2 | -------------------------------------------------------------------------------- /src/briefcase/platforms/tvOS/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | DEFAULT_OUTPUT_FORMAT = 'xcode' 3 | -------------------------------------------------------------------------------- /src/briefcase/platforms/watchOS/xcode.py: -------------------------------------------------------------------------------- 1 | # An implementation would go here! 2 | -------------------------------------------------------------------------------- /src/briefcase/platforms/wearos/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | DEFAULT_OUTPUT_FORMAT = 'apk' 3 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from setuptools import setup 3 | 4 | setup() 5 | -------------------------------------------------------------------------------- /src/briefcase/platforms/django/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | DEFAULT_OUTPUT_FORMAT = 'project' 3 | -------------------------------------------------------------------------------- /src/briefcase/platforms/watchOS/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | DEFAULT_OUTPUT_FORMAT = 'xcode' 3 | -------------------------------------------------------------------------------- /tests/integrations/xcode/security/no-identities.out: -------------------------------------------------------------------------------- 1 | 0 valid identities found 2 | -------------------------------------------------------------------------------- /changes/266.feature: -------------------------------------------------------------------------------- 1 | Converted Briefcase to be a PEP518 tool, rather than a setuptools extension. 2 | -------------------------------------------------------------------------------- /docs/_static/images/briefcase.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/briefcase/master/docs/_static/images/briefcase.png -------------------------------------------------------------------------------- /docs/how-to/PyStackTraceOnXCode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/probonopd/briefcase/master/docs/how-to/PyStackTraceOnXCode.png -------------------------------------------------------------------------------- /docs/requirements_docs.txt: -------------------------------------------------------------------------------- 1 | sphinx 2 | sphinxcontrib-spelling 3 | pyenchant 4 | sphinx-autobuild 5 | sphinx_rtd_theme 6 | sphinx_tabs==1.1.8 7 | -------------------------------------------------------------------------------- /tests/integrations/xcode/simctl/no-runtimes.json: -------------------------------------------------------------------------------- 1 | { 2 | "devicetypes" : [ 3 | ], 4 | "runtimes" : [ 5 | ], 6 | "devices" : { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /tests/integrations/xcode/simctl/README: -------------------------------------------------------------------------------- 1 | This directory contains test fixtures for Xcode integration. 2 | 3 | Each of the files is the verbatim output generated by `xcrun simctl`. 4 | -------------------------------------------------------------------------------- /tests/integrations/xcode/security/one-identity.out: -------------------------------------------------------------------------------- 1 | 1) 38EBD6F8903EC63C238B04C1067833814CE47CA3 "Developer ID Application: Example Corporation Ltd (Z2K4383DLE)" 2 | 1 valid identity found 3 | -------------------------------------------------------------------------------- /src/briefcase/platforms/macOS/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | DEFAULT_OUTPUT_FORMAT = 'dmg' 3 | 4 | 5 | class macOSMixin: 6 | platform = 'macOS' 7 | 8 | def verify_tools(self): 9 | pass 10 | -------------------------------------------------------------------------------- /src/briefcase/platforms/linux/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | DEFAULT_OUTPUT_FORMAT = 'appimage' 3 | 4 | 5 | class LinuxMixin: 6 | platform = 'linux' 7 | 8 | def verify_tools(self): 9 | pass 10 | -------------------------------------------------------------------------------- /src/briefcase/platforms/windows/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | DEFAULT_OUTPUT_FORMAT = 'msi' 3 | 4 | 5 | class WindowsMixin: 6 | platform = 'windows' 7 | 8 | def verify_tools(self): 9 | pass 10 | -------------------------------------------------------------------------------- /docs/reference/platforms/linux/index.rst: -------------------------------------------------------------------------------- 1 | ===== 2 | Linux 3 | ===== 4 | 5 | The default output format for Linux is :doc:`AppImage <./appimage>`. 6 | 7 | .. toctree:: 8 | :maxdepth: 1 9 | 10 | appimage 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | *~ 3 | .*.sw[op] 4 | *.egg-info 5 | /dist 6 | /build 7 | docs/_build/ 8 | distribute-* 9 | .DS_Store 10 | .python-version 11 | .pytest_cache 12 | venv/ 13 | .vscode/ 14 | .eggs/ 15 | /local 16 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | BeeWare <3's contributions! 4 | 5 | Please be aware, BeeWare operates under a Code of Conduct. 6 | 7 | See [CONTRIBUTING to BeeWare](http://beeware.org/contributing) for details. 8 | 9 | -------------------------------------------------------------------------------- /docs/reference/platforms/windows/index.rst: -------------------------------------------------------------------------------- 1 | ======= 2 | Windows 3 | ======= 4 | 5 | The default output format for Windows is an :doc:`MSI Installer <./msi>`. 6 | 7 | .. toctree:: 8 | :maxdepth: 1 9 | 10 | msi 11 | -------------------------------------------------------------------------------- /docs/reference/platforms/index.rst: -------------------------------------------------------------------------------- 1 | ================ 2 | Platform support 3 | ================ 4 | 5 | .. toctree:: 6 | :maxdepth: 2 7 | 8 | macOS/index 9 | windows/index 10 | linux/index 11 | iOS 12 | android 13 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.towncrier] 2 | directory = "changes" 3 | package = "briefcase" 4 | package_dir = "src" 5 | filename = "docs/background/releases.rst" 6 | title_format = "{version} ({project_date})" 7 | template = "changes/template.rst" 8 | -------------------------------------------------------------------------------- /docs/background/index.rst: -------------------------------------------------------------------------------- 1 | .. _background: 2 | 3 | =============== 4 | About Briefcase 5 | =============== 6 | 7 | .. toctree:: 8 | :maxdepth: 1 9 | :glob: 10 | 11 | faq 12 | community 13 | success 14 | releases 15 | -------------------------------------------------------------------------------- /docs/reference/commands/index.rst: -------------------------------------------------------------------------------- 1 | ================= 2 | Command reference 3 | ================= 4 | 5 | .. toctree:: 6 | :maxdepth: 1 7 | 8 | new 9 | dev 10 | create 11 | update 12 | build 13 | run 14 | package 15 | publish 16 | -------------------------------------------------------------------------------- /docs/reference/index.rst: -------------------------------------------------------------------------------- 1 | .. _reference: 2 | 3 | ========= 4 | Reference 5 | ========= 6 | 7 | This is the technical reference for public APIs provided by Briefcase. 8 | 9 | .. toctree:: 10 | :maxdepth: 2 11 | 12 | configuration 13 | commands/index 14 | platforms/index 15 | -------------------------------------------------------------------------------- /docs/reference/platforms/macOS/index.rst: -------------------------------------------------------------------------------- 1 | ===== 2 | macOS 3 | ===== 4 | 5 | The default output format for macOS is a :doc:`DMG <./dmg>`. 6 | 7 | Briefcase also supports creating :doc:`.app bundles <./app>`. 8 | 9 | .. toctree:: 10 | :maxdepth: 1 11 | 12 | dmg 13 | app 14 | -------------------------------------------------------------------------------- /docs/how-to/internal/index.rst: -------------------------------------------------------------------------------- 1 | ====================== 2 | Internal How-to guides 3 | ====================== 4 | 5 | These guides are for the maintainers of the Briefcase project, documenting 6 | internal project procedures. 7 | 8 | .. toctree:: 9 | :maxdepth: 2 10 | :glob: 11 | 12 | release 13 | -------------------------------------------------------------------------------- /tests/integrations/xcode/simctl/no-devices.json: -------------------------------------------------------------------------------- 1 | { 2 | "devices" : { 3 | "com.apple.CoreSimulator.SimRuntime.tvOS-13-2" : [ 4 | 5 | ], 6 | "com.apple.CoreSimulator.SimRuntime.watchOS-6-1" : [ 7 | 8 | ], 9 | "com.apple.CoreSimulator.SimRuntime.iOS-13-2" : [ 10 | 11 | ] 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/briefcase/commands/__init__.py: -------------------------------------------------------------------------------- 1 | from .build import BuildCommand # noqa 2 | from .create import CreateCommand # noqa 3 | from .dev import DevCommand # noqa 4 | from .new import NewCommand # noqa 5 | from .package import PackageCommand # noqa 6 | from .publish import PublishCommand # noqa 7 | from .run import RunCommand # noqa 8 | from .update import UpdateCommand # noqa 9 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Briefcase was originally created in July 2015. 2 | 3 | The PRIMARY AUTHORS are (and/or have been): 4 | Russell Keith-Magee 5 | 6 | And here is an inevitably incomplete list of MUCH-APPRECIATED CONTRIBUTORS -- 7 | people who have submitted patches, reported bugs, added translations, helped 8 | answer newbie questions, and generally made Briefcase that much better: 9 | 10 | -------------------------------------------------------------------------------- /tests/integrations/xcode/security/multiple-identities.out: -------------------------------------------------------------------------------- 1 | 1) 38EBD6F8903EC63C238B04C1067833814CE47CA3 "Developer ID Application: Example Corporation Ltd (Z2K4383DLE)" 2 | 2) 11E77FB58F13F6108B38110D5D92233C58ED38C5 "iPhone Developer: Jane Smith (BXAH5H869S)" 3 | 3) F8903EC63C238B04C1067833814CE47CA338EBD6 "Developer ID Application: Other Corporation Ltd (83DLZ2K43E)" 4 | 3 valid identities found 5 | -------------------------------------------------------------------------------- /docs/background/success.rst: -------------------------------------------------------------------------------- 1 | Success Stories 2 | =============== 3 | 4 | Want to see examples of Briefcase in use? Here's some: 5 | 6 | * `Travel Tips `_ is 7 | an app in the iOS App Store that was packaged for distribution using 8 | Briefcase. 9 | 10 | * `Mu `_ is a simple code editor for beginner programmers. 11 | It uses Briefcase to prepare a macOS installer. 12 | -------------------------------------------------------------------------------- /tests/commands/new/test_make_domain.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | 4 | @pytest.mark.parametrize( 5 | 'bundle, candidate', 6 | [ 7 | ('com.example', 'example.com'), 8 | ('com.example.more', 'more.example.com'), 9 | ] 10 | ) 11 | def test_make_app_name(new_command, bundle, candidate): 12 | "A bundle can be converted into a domain name." 13 | app_name = new_command.make_domain(bundle) 14 | assert app_name == candidate 15 | -------------------------------------------------------------------------------- /tests/platforms/conftest.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from briefcase.config import AppConfig 4 | 5 | 6 | @pytest.fixture 7 | def first_app_config(): 8 | return AppConfig( 9 | app_name='first-app', 10 | project_name='First Project', 11 | formal_name='First App', 12 | bundle='com.example', 13 | version='0.0.1', 14 | description='The first simple app', 15 | sources=['src/first_app'], 16 | ) 17 | -------------------------------------------------------------------------------- /src/briefcase/__init__.py: -------------------------------------------------------------------------------- 1 | __all__ = [ 2 | '__version__', 3 | ] 4 | 5 | # Examples of valid version strings 6 | # __version__ = '1.2.3.dev1' # Development release 1 7 | # __version__ = '1.2.3a1' # Alpha Release 1 8 | # __version__ = '1.2.3b1' # Beta Release 1 9 | # __version__ = '1.2.3rc1' # RC Release 1 10 | # __version__ = '1.2.3' # Final Release 11 | # __version__ = '1.2.3.post1' # Post Release 1 12 | 13 | __version__ = '0.3.0.dev5' 14 | -------------------------------------------------------------------------------- /tests/commands/new/test_call.py: -------------------------------------------------------------------------------- 1 | 2 | def test_new_app(new_command): 3 | "A new application can be created." 4 | 5 | # Configure no command line options 6 | options = new_command.parse_options([]) 7 | 8 | # Run the run command 9 | new_command(**options) 10 | 11 | # The right sequence of things will be done 12 | assert new_command.actions == [ 13 | # Run the first app 14 | ('new', {'template': None, 'verbosity': 1}), 15 | ] 16 | -------------------------------------------------------------------------------- /docs/reference/platforms/android.rst: -------------------------------------------------------------------------------- 1 | ======= 2 | Android 3 | ======= 4 | 5 | .. note:: 6 | 7 | The BeeWare project *has* tooling for Android. Unfortunately, due to some 8 | recent changes in the Android ecosystem, combined with some changes in Toga 9 | itself, means that our Android tooling is currently broken. We're working 10 | on it, and hope to have a solution in the very near future. 11 | 12 | When generating an Android project, Briefcase produces a Gradle project. 13 | -------------------------------------------------------------------------------- /tests/integrations/xcode/simctl/single-device.json: -------------------------------------------------------------------------------- 1 | { 2 | "devices" : { 3 | "com.apple.CoreSimulator.SimRuntime.tvOS-13-2" : [ 4 | 5 | ], 6 | "com.apple.CoreSimulator.SimRuntime.watchOS-6-1" : [ 7 | 8 | ], 9 | "com.apple.CoreSimulator.SimRuntime.iOS-13-2" : [ 10 | { 11 | "state" : "Booted", 12 | "isAvailable" : true, 13 | "name" : "iPhone 11", 14 | "udid" : "2D3503A3-6EB9-4B37-9B17-C7EFEF2FA32D" 15 | } 16 | ] 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tests/integrations/xcode/simctl/single-device-booted.json: -------------------------------------------------------------------------------- 1 | { 2 | "devices" : { 3 | "com.apple.CoreSimulator.SimRuntime.tvOS-13-2" : [ 4 | 5 | ], 6 | "com.apple.CoreSimulator.SimRuntime.watchOS-6-1" : [ 7 | 8 | ], 9 | "com.apple.CoreSimulator.SimRuntime.iOS-13-2" : [ 10 | { 11 | "state" : "Booted", 12 | "isAvailable" : true, 13 | "name" : "iPhone 11", 14 | "udid" : "2D3503A3-6EB9-4B37-9B17-C7EFEF2FA32D" 15 | } 16 | ] 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tests/integrations/xcode/simctl/single-device-unknown.json: -------------------------------------------------------------------------------- 1 | { 2 | "devices" : { 3 | "com.apple.CoreSimulator.SimRuntime.tvOS-13-2" : [ 4 | 5 | ], 6 | "com.apple.CoreSimulator.SimRuntime.watchOS-6-1" : [ 7 | 8 | ], 9 | "com.apple.CoreSimulator.SimRuntime.iOS-13-2" : [ 10 | { 11 | "state" : "Booting", 12 | "isAvailable" : true, 13 | "name" : "iPhone 11", 14 | "udid" : "2D3503A3-6EB9-4B37-9B17-C7EFEF2FA32D" 15 | } 16 | ] 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tests/integrations/xcode/simctl/single-device-shutdown.json: -------------------------------------------------------------------------------- 1 | { 2 | "devices" : { 3 | "com.apple.CoreSimulator.SimRuntime.tvOS-13-2" : [ 4 | 5 | ], 6 | "com.apple.CoreSimulator.SimRuntime.watchOS-6-1" : [ 7 | 8 | ], 9 | "com.apple.CoreSimulator.SimRuntime.iOS-13-2" : [ 10 | { 11 | "state" : "Shutdown", 12 | "isAvailable" : true, 13 | "name" : "iPhone 11", 14 | "udid" : "2D3503A3-6EB9-4B37-9B17-C7EFEF2FA32D" 15 | } 16 | ] 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tests/integrations/xcode/simctl/single-device-shutting-down.json: -------------------------------------------------------------------------------- 1 | { 2 | "devices" : { 3 | "com.apple.CoreSimulator.SimRuntime.tvOS-13-2" : [ 4 | 5 | ], 6 | "com.apple.CoreSimulator.SimRuntime.watchOS-6-1" : [ 7 | 8 | ], 9 | "com.apple.CoreSimulator.SimRuntime.iOS-13-2" : [ 10 | { 11 | "state" : "Shutting Down", 12 | "isAvailable" : true, 13 | "name" : "iPhone 11", 14 | "udid" : "2D3503A3-6EB9-4B37-9B17-C7EFEF2FA32D" 15 | } 16 | ] 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tests/commands/new/test_make_module_name.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | 4 | @pytest.mark.parametrize( 5 | 'app_name, candidate', 6 | [ 7 | ('helloworld', 'helloworld'), 8 | ('HelloWorld', 'HelloWorld'), 9 | ('hello-world', 'hello_world'), 10 | ('hello_world', 'hello_world'), 11 | ] 12 | ) 13 | def test_make_module_name(new_command, app_name, candidate): 14 | "An app name can be converted into a valid class name." 15 | module_name = new_command.make_module_name(app_name) 16 | assert module_name == candidate 17 | -------------------------------------------------------------------------------- /src/briefcase/__main__.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | from .cmdline import parse_cmdline 4 | from .exceptions import BriefcaseError 5 | 6 | 7 | def main(): 8 | try: 9 | command, options = parse_cmdline(sys.argv[1:]) 10 | command.parse_config('pyproject.toml') 11 | command(**options) 12 | result = 0 13 | except BriefcaseError as e: 14 | print(e, file=sys.stdout if e.error_code == 0 else sys.stderr) 15 | result = e.error_code 16 | 17 | sys.exit(result) 18 | 19 | 20 | if __name__ == '__main__': 21 | main() 22 | -------------------------------------------------------------------------------- /docs/how-to/index.rst: -------------------------------------------------------------------------------- 1 | .. _how-to: 2 | 3 | ============= 4 | How-to guides 5 | ============= 6 | 7 | How-to guides are recipes that take the user through steps in key subjects. 8 | They are more advanced than tutorials and assume a lot more about what the user 9 | already knows than tutorials do, and unlike documents in the tutorial they can 10 | stand alone. 11 | 12 | .. toctree:: 13 | :maxdepth: 2 14 | :glob: 15 | 16 | contribute-code 17 | contribute-docs 18 | code-signing/index 19 | See errors on iOS 20 | internal/index 21 | -------------------------------------------------------------------------------- /.github/workflows/build_status.yml: -------------------------------------------------------------------------------- 1 | name: Build status 2 | on: 3 | push: 4 | branches: 5 | - master 6 | 7 | jobs: 8 | test: 9 | name: Run tests 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v1 13 | - name: Set up Python 3.5 14 | uses: actions/setup-python@v1 15 | with: 16 | python-version: 3.5 17 | - name: Install dependencies 18 | run: | 19 | pip install --upgrade pip setuptools pytest-tldr 20 | pip install -e . 21 | - name: Test 22 | run: | 23 | python setup.py test 24 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include beekeeper.yml 2 | include CONTRIBUTING.md 3 | include README.rst 4 | include AUTHORS 5 | include LICENSE.txt 6 | include requirements*.txt 7 | include docs/spelling_wordlist 8 | include tests/integrations/xcode/simctl/README 9 | recursive-include briefcase *.py 10 | recursive-include docs *.bat 11 | recursive-include docs *.png 12 | recursive-include docs *.py 13 | recursive-include docs *.rst 14 | recursive-include docs *.txt 15 | recursive-include docs Makefile 16 | recursive-exclude docs/_build * 17 | recursive-include tests *.py 18 | recursive-include tests *.json 19 | -------------------------------------------------------------------------------- /docs/tutorial/index.rst: -------------------------------------------------------------------------------- 1 | .. _tutorial: 2 | 3 | ======== 4 | Tutorial 5 | ======== 6 | 7 | Briefcase is a packaging tool - but first you need something to package. The 8 | best way to learn about Briefcase is to see it working with the rest of the 9 | BeeWare suite of tools. 10 | 11 | `The BeeWare tutorial `__ walks you 12 | through the process of building a native Python application from scratch. 13 | 14 | Once you've done that tutorial, the :doc:`Briefcase How-To Guides 15 | <../how-to/index>` provide details on performing specific tasks with Briefcase. 16 | -------------------------------------------------------------------------------- /tests/commands/new/test_is_valid_url.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | 4 | @pytest.mark.parametrize( 5 | 'url', 6 | [ 7 | 'https://example.com', 8 | ] 9 | ) 10 | def test_valid_url(new_command, url): 11 | "Test that valid URLs are accepted" 12 | assert new_command.is_valid_url(url) 13 | 14 | 15 | @pytest.mark.parametrize( 16 | 'url', 17 | [ 18 | 'not a URL!', # Free text. 19 | ] 20 | ) 21 | def test_invalid_url(new_command, url): 22 | "Test that invalid URLs are rejected" 23 | with pytest.raises(ValueError): 24 | new_command.is_valid_url(url) 25 | -------------------------------------------------------------------------------- /tests/platforms/linux/appimage/test_create.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | from briefcase.platforms.linux.appimage import LinuxAppImageCreateCommand 4 | 5 | 6 | def test_support_package_url(first_app_config, tmp_path): 7 | command = LinuxAppImageCreateCommand(base_path=tmp_path) 8 | 9 | # Set some properties of the host system for test purposes. 10 | command.host_arch = 'wonky' 11 | command.platform = 'tester' 12 | 13 | assert command.support_package_url_query == [ 14 | ('platform', 'tester'), 15 | ('version', '3.{minor}'.format(minor=sys.version_info.minor)), 16 | ('arch', 'wonky'), 17 | ] 18 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Create Release 2 | 3 | on: 4 | push: 5 | tags: 6 | - 'v*' 7 | 8 | jobs: 9 | build: 10 | name: Create Release 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Checkout code 14 | uses: actions/checkout@master 15 | - name: Create Release 16 | id: create_release 17 | uses: actions/create-release@v1 18 | env: 19 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 20 | with: 21 | tag_name: ${{ github.ref }} 22 | release_name: Release ${{ github.ref }} 23 | draft: true 24 | prerelease: false 25 | -------------------------------------------------------------------------------- /tests/commands/new/test_is_valid_email.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | 4 | @pytest.mark.parametrize( 5 | 'email', 6 | [ 7 | 'foo@example.com', 8 | ] 9 | ) 10 | def test_valid_email(new_command, email): 11 | "Test that valid email addresses are accepted" 12 | assert new_command.is_valid_email(email) 13 | 14 | 15 | @pytest.mark.parametrize( 16 | 'email', 17 | [ 18 | 'not a email address!', # Free text. 19 | ] 20 | ) 21 | def test_invalid_email(new_command, email): 22 | "Test that invalid email addresses are rejected" 23 | with pytest.raises(ValueError): 24 | new_command.is_valid_email(email) 25 | -------------------------------------------------------------------------------- /tests/platforms/windows/msi/test_mixin.py: -------------------------------------------------------------------------------- 1 | from briefcase.platforms.windows.msi import WindowsMSICreateCommand 2 | 3 | 4 | def test_binary_path(first_app_config, tmp_path): 5 | command = WindowsMSICreateCommand(base_path=tmp_path) 6 | binary_path = command.binary_path(first_app_config) 7 | 8 | assert binary_path == tmp_path / 'windows' / 'First App' 9 | 10 | 11 | def test_distribution_path(first_app_config, tmp_path): 12 | command = WindowsMSICreateCommand(base_path=tmp_path) 13 | distribution_path = command.distribution_path(first_app_config) 14 | 15 | assert distribution_path == tmp_path / 'windows' / 'First App-0.0.1.msi' 16 | -------------------------------------------------------------------------------- /tests/commands/new/test_make_class_name.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | 4 | @pytest.mark.parametrize( 5 | 'formal_name, candidate', 6 | [ 7 | ('Hello World', 'HelloWorld'), 8 | ('Hello World!', 'HelloWorld'), 9 | ('Hello! World', 'HelloWorld'), 10 | ('Hello_World', 'Hello_World'), 11 | ('Hello-World', 'HelloWorld'), 12 | ('24 Jump Street', '_24JumpStreet'), 13 | ] 14 | ) 15 | def test_make_class_name(new_command, formal_name, candidate): 16 | "A formal name can be converted into a valid class name." 17 | class_name = new_command.make_class_name(formal_name) 18 | assert class_name == candidate 19 | -------------------------------------------------------------------------------- /tests/platforms/macOS/app/test_mixin.py: -------------------------------------------------------------------------------- 1 | from briefcase.platforms.macOS.app import macOSAppCreateCommand 2 | 3 | 4 | def test_binary_path(first_app_config, tmp_path): 5 | command = macOSAppCreateCommand(base_path=tmp_path) 6 | binary_path = command.binary_path(first_app_config) 7 | 8 | assert binary_path == tmp_path / 'macOS' / 'First App' / 'First App.app' 9 | 10 | 11 | def test_distribution_path(first_app_config, tmp_path): 12 | command = macOSAppCreateCommand(base_path=tmp_path) 13 | distribution_path = command.distribution_path(first_app_config) 14 | 15 | assert distribution_path == tmp_path / 'macOS' / 'First App' / 'First App.app' 16 | -------------------------------------------------------------------------------- /tests/commands/new/test_make_app_name.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | 4 | @pytest.mark.parametrize( 5 | 'formal_name, candidate', 6 | [ 7 | ('Hello World', 'helloworld'), 8 | ('Hello World!', 'helloworld'), 9 | ('Hello! World', 'helloworld'), 10 | ('Hello-World', 'helloworld'), 11 | ] 12 | ) 13 | def test_make_app_name(new_command, formal_name, candidate): 14 | "A formal name can be converted into a valid app name." 15 | app_name = new_command.make_app_name(formal_name) 16 | assert app_name == candidate 17 | # Double check - the app name passes the validity check. 18 | assert new_command.is_valid_app_name(app_name) 19 | -------------------------------------------------------------------------------- /docs/how-to/code-signing/index.rst: -------------------------------------------------------------------------------- 1 | ================================= 2 | Obtaining a Code Signing identity 3 | ================================= 4 | 5 | If you are intending to distribute an application, it is advisable (and, on 6 | some platforms, necessary) to code sign your application. This is a 7 | cryptographic process that identifies you as a developer, and identifies your 8 | application as something that has been distributed by you. 9 | 10 | The process of obtaining a code signing identity is slightly different on 11 | every platform. The following are guides for every platform that Briefcase 12 | supports: 13 | 14 | .. toctree:: 15 | :maxdepth: 1 16 | 17 | macOS 18 | -------------------------------------------------------------------------------- /docs/how-to/see_errors_on_ios.rst: -------------------------------------------------------------------------------- 1 | See Errors on iOS 2 | ========================= 3 | 4 | If you have a beeware iOS project that has a crash, it can be difficult to see 5 | the stacktrace. Here's how to do it - 6 | 7 | 1. Build your iOS project. You don't have to start it. 8 | 9 | 2. Open that iOS project in Xcode. Click the Run button (looks like an arrow) 10 | and wait for the simulator to open. Cause the app to crash. 11 | 12 | 3. Your stack trace ought to appear in the 'debugger area' at the bottom of the 13 | screen. If you can't see that area, you may have to activate it with 14 | ``View`` > ``Debug Area`` > ``Show Debug Area`` 15 | 16 | .. image:: PyStackTraceOnXCode.png 17 | -------------------------------------------------------------------------------- /docs/reference/commands/new.rst: -------------------------------------------------------------------------------- 1 | === 2 | new 3 | === 4 | 5 | Start a new Briefcase project. Runs a wizard to ask questions about your new 6 | application, and creates a stub project using the details provided. 7 | 8 | Usage 9 | ===== 10 | 11 | To start a new application, run:: 12 | 13 | $ briefcase new 14 | 15 | Options 16 | ======= 17 | 18 | The following options can be provided at the command line. 19 | 20 | ``-t