Source code for projspec.proj.briefcase

import os

from projspec.proj import ProjectSpec
from projspec.utils import AttrDict, run_subprocess, make_and_copy


def supported(apps: dict, app: str, *config) -> bool:
    """Check if an app is supported on a given platform.

    Looks in the metadata for app for a `supported` key in each
    level named in config. If there isn't a table for the named config,
    or the table contains a `supported = false` declaration, skip it.

    For example, `supported(apps, "foo", "linux", "system")` will check for:

    * A "linux" table; if there isn't, return False
    * A `supported` key in the "linux" table (defaulting True)
    * A "linux.system" table; if there isn't return False
    * A `supported` key in the "linux.system" table (defaulting True)

    If any of those results return False, the app isn't supported.
    """
    plat = apps[app].get(config[0], {"supported": False})
    supp = plat.get("supported", True)
    for part in config[1:]:
        try:
            plat = plat.get(part, {"supported": False})
            supp &= plat.get("supported", True)
        except KeyError:
            # Platform config doesn't exist
            supp = False

    return supp


[docs] class Briefcase(ProjectSpec): icon = "💼" spec_doc = "https://briefcase.readthedocs.io/en/stable/reference/configuration.html" def match(self) -> bool: return "briefcase" in self.proj.pyproject.get("tool", {}) def parse(self) -> None: from projspec.artifact.installable import ( Architecture, SystemInstallablePackage, ) briefcase_meta = self.proj.pyproject["tool"]["briefcase"] cont = AttrDict() self._contents = cont self._artifacts = AttrDict() apps = briefcase_meta.get("app", {}) # TODO: app name is not encoded in the artifact, so multiple outputs # will overwrite. for app in apps: for filetype in ("zip", "dmg", "pkg"): if supported(apps, app, "macOS"): self._artifacts[filetype] = SystemInstallablePackage( proj=self.proj, ext=filetype, arch=Architecture.MACOS, cmd=["briefcase", "package", "-a", app, "-p", filetype], ) # iOS doesn't produce an artifact directly, but it's included for # completeness. if supported(apps, app, "iOS"): self._artifacts["iOS"] = SystemInstallablePackage( proj=self.proj, ext="ipa", arch=Architecture.IOS, cmd=["briefcase", "package", "iOS", "-a", app, "-p", "ipa"], ) if supported(apps, app, "linux", "system", "rhel"): self._artifacts["linux-rpm"] = SystemInstallablePackage( proj=self.proj, ext="rpm", arch=Architecture.LINUX, cmd=["briefcase", "package", "-a", app, "-p", "rpm"], ) if supported(apps, app, "linux", "system", "suse"): self._artifacts["linux-rpm"] = SystemInstallablePackage( proj=self.proj, ext="rpm", arch=Architecture.LINUX, cmd=["briefcase", "package", "-a", app, "-p", "rpm"], ) if supported(apps, app, "linux", "system", "debian"): self._artifacts["linux-deb"] = SystemInstallablePackage( proj=self.proj, ext="deb", arch=Architecture.LINUX, cmd=["briefcase", "package", "-a", app, "-p", "deb"], ) if supported(apps, app, "linux", "system", "arch"): self._artifacts["linux-pkg"] = SystemInstallablePackage( proj=self.proj, ext="pkg.tar.zstd", arch=Architecture.LINUX, cmd=["briefcase", "package", "-a", app, "-p", "pkg"], ) if supported(apps, app, "linux", "flatpak"): self._artifacts["linux-flatpak"] = SystemInstallablePackage( proj=self.proj, ext="flatpack", arch=Architecture.LINUX, cmd=[ "briefcase", "package", "linux", "flatpak", "-a", app, "-p", "flatpak", ], ) if supported(apps, app, "windows"): self._artifacts["windows-msi"] = SystemInstallablePackage( proj=self.proj, ext="msi", arch=Architecture.WINDOWS, cmd=["briefcase", "package", "-a", app, "-p", "msi"], ) if supported(apps, app, "android"): for fmt, Artifact, arg in [ ("android-aab", SystemInstallablePackage, "aab"), ("android-apk", SystemInstallablePackage, "apk"), ]: self._artifacts[fmt] = Artifact( proj=self.proj, ext=fmt, arch=Architecture.ANDROID, cmd=[ "briefcase", "package", "android", "-a", app, "-p", arg, ], ) if supported(apps, app, "web"): self._artifacts["web-zip"] = SystemInstallablePackage( proj=self.proj, ext="web.zip", arch=Architecture.WEB, cmd=[ "briefcase", "package", "web", "-a", app, "-p", "zip", ], ) @staticmethod def _create(path: str) -> None: # TODO: this version will overwrite any pyproject.toml with make_and_copy(path, sub="helloworld", mkdir=True) as tmp: run_subprocess(["briefcase", "new", "--no-input"], cwd=tmp, output=False)