Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drop Python 3.8 support and bump macOS/iOS template epoch #1934

Merged
merged 9 commits into from
Aug 15, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 2 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ jobs:
fail-fast: false
matrix:
platform: [ "macos-12", "macos-14", "windows-latest", "ubuntu-latest" ]
python-version: [ "3.8", "3.12", "3.13-dev" ]
python-version: [ "3.9", "3.12", "3.13-dev" ]
include:
- experimental: false
- platform: "ubuntu-latest"
Expand All @@ -80,10 +80,6 @@ jobs:
# Allow dev Python to fail without failing entire job
- python-version: "3.13-dev"
experimental: true
exclude:
# macos-14 (i.e. arm64) does not support Python 3.8
- platform: "macos-14"
python-version: "3.8"
steps:
- name: Checkout
uses: actions/checkout@v4.1.7
Expand Down Expand Up @@ -145,7 +141,7 @@ jobs:
with:
# Use minimum version of python for coverage to avoid phantom branches
# https://github.com/nedbat/coveragepy/issues/1572#issuecomment-1522546425
python-version: "3.8"
python-version: "3.9"

- name: Install Tox
uses: beeware/.github/.github/actions/install-requirement@main
Expand Down
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ repos:
rev: v3.17.0
hooks:
- id: pyupgrade
args: [--py38-plus]
args: [--py39-plus]
- repo: https://github.com/PyCQA/isort
rev: 5.13.2
hooks:
Expand Down
1 change: 1 addition & 0 deletions changes/1934.removal.1.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Support for Python 3.8 was dropped.
1 change: 1 addition & 0 deletions changes/1934.removal.2.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
macOS and iOS templates have both had an epoch increase. macOS and iOS projects created with previous versions of Briefcase will need to be re-generated.
2 changes: 1 addition & 1 deletion docs/background/faq.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Frequently Asked Questions
What version of Python does Briefcase support?
----------------------------------------------

Python 3.8 or higher.
Python 3.9 or higher.

What platforms does Briefcase support?
--------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion docs/reference/platforms/linux/system.rst
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ normalization of code name and version is performed, so ``ubuntu:jammy`` and
same version).

You can specify any identifier you want, provided the distribution is still
supported by the vendor, and system Python is Python 3.8 or later.
supported by the vendor, and system Python is Python 3.9 or later.

The following Linux vendors are known to work as Docker targets:

Expand Down
15 changes: 4 additions & 11 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ dynamic = ["version"]
name = "briefcase"
description = "Tools to support converting a Python project into a standalone native application."
readme = "README.rst"
requires-python = ">= 3.8"
requires-python = ">= 3.9"
license.text = "New BSD"
authors = [
{name="Russell Keith-Magee", email="russell@keith-magee.com"},
Expand Down Expand Up @@ -48,7 +48,6 @@ classifiers = [
"License :: OSI Approved :: BSD License",
"Operating System :: OS Independent",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
Expand Down Expand Up @@ -98,9 +97,7 @@ dependencies = [
dev = [
"coverage[toml] == 7.6.0",
"coverage-conditional-plugin == 0.9.0",
# Pre-commit 3.6.0 deprecated support for Python 3.8
"pre-commit == 3.5.0 ; python_version < '3.9'",
"pre-commit == 3.8.0 ; python_version >= '3.9'",
"pre-commit == 3.8.0",
"pytest == 8.3.2",
"pytest-xdist == 3.6.1",
"setuptools_scm == 8.1.0",
Expand All @@ -109,13 +106,9 @@ dev = [
docs = [
"furo == 2024.7.18",
"pyenchant == 3.2.2",
# Sphinx 7.2 deprecated support for Python 3.8
"sphinx == 7.1.2 ; python_version < '3.9'",
"sphinx == 7.4.7 ; python_version >= '3.9'",
"sphinx == 7.4.7",
"sphinx_tabs == 3.4.5",
# Sphinx 2024.2.4 deprecated support for Python 3.8
"sphinx-autobuild == 2021.3.14 ; python_version < '3.9'",
"sphinx-autobuild == 2024.4.16 ; python_version >= '3.9'",
"sphinx-autobuild == 2024.4.16",
"sphinx-copybutton == 0.5.2",
"sphinxcontrib-spelling == 8.0.0",
]
Expand Down
3 changes: 1 addition & 2 deletions src/briefcase/commands/new.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@
import sys
import unicodedata
from collections import OrderedDict
from collections.abc import Sequence
from collections.abc import Iterable, Sequence
from email.utils import parseaddr
from typing import Iterable

if sys.version_info >= (3, 10): # pragma: no-cover-if-lt-py310
from importlib.metadata import entry_points
Expand Down
3 changes: 2 additions & 1 deletion src/briefcase/console.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@
import textwrap
import time
import traceback
from collections.abc import Iterable
from contextlib import contextmanager
from datetime import datetime
from enum import IntEnum
from pathlib import Path
from typing import Callable, Iterable
from typing import Callable

from rich.console import Console as RichConsole
from rich.control import strip_control_codes
Expand Down
2 changes: 1 addition & 1 deletion src/briefcase/integrations/docker.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
import socket
import subprocess
import sys
from collections.abc import Iterable, Mapping
from functools import lru_cache
from pathlib import Path, PosixPath, PurePosixPath
from typing import Iterable, Mapping

from packaging.version import InvalidVersion, Version

Expand Down
2 changes: 1 addition & 1 deletion src/briefcase/integrations/file.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from briefcase.integrations.base import Tool, ToolCache

if TYPE_CHECKING:
from typing import Iterable, Sequence
from collections.abc import Iterable, Sequence
rmartin16 marked this conversation as resolved.
Show resolved Hide resolved


class File(Tool):
Expand Down
4 changes: 2 additions & 2 deletions src/briefcase/integrations/subprocess.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@
import sys
import threading
import time
from collections.abc import Callable
from collections.abc import Callable, Iterator, Mapping, Sequence
from functools import wraps
from pathlib import Path
from subprocess import CompletedProcess
from typing import Iterator, Mapping, Sequence, TypeVar, Union
from typing import TypeVar, Union

import psutil

Expand Down
2 changes: 1 addition & 1 deletion src/briefcase/integrations/windows_sdk.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from __future__ import annotations

import subprocess
from collections.abc import Iterator
from pathlib import Path
from typing import Iterator

# winreg can only be imported on Windows
try:
Expand Down
4 changes: 2 additions & 2 deletions src/briefcase/platforms/iOS/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ class iOSMixin:
supported_host_os_reason = (
"iOS applications require Xcode, which is only available on macOS."
)
# 0.3.16 introduced new-style dylib support.
platform_target_version = "0.3.16"
# 0.3.20 introduced PEP 730-style dynamic libraries.
platform_target_version = "0.3.20"

def verify_tools(self):
Xcode.verify(self.tools, min_version=(13, 0, 0))
Expand Down
24 changes: 14 additions & 10 deletions src/briefcase/platforms/iOS/xcode.py
Original file line number Diff line number Diff line change
Expand Up @@ -514,11 +514,14 @@ def run_app(
# Try to uninstall the app first. If the app hasn't been installed
# before, this will still succeed.
self.logger.info(f"Installing {label}...", prefix=app.app_name)
with self.input.wait_bar(
"Uninstalling any existing app version..."
) as keep_alive, self.tools.subprocess.Popen(
["xcrun", "simctl", "uninstall", udid, app.bundle_identifier]
) as uninstall_popen:
with (
self.input.wait_bar(
"Uninstalling any existing app version..."
) as keep_alive,
self.tools.subprocess.Popen(
["xcrun", "simctl", "uninstall", udid, app.bundle_identifier]
) as uninstall_popen,
):
while (ret_code := uninstall_popen.poll()) is None:
keep_alive.update()
time.sleep(0.25)
Expand All @@ -529,11 +532,12 @@ def run_app(
)

# Install the app.
with self.input.wait_bar(
f"Installing new {label} version..."
) as keep_alive, self.tools.subprocess.Popen(
["xcrun", "simctl", "install", udid, self.binary_path(app)]
) as install_popen:
with (
self.input.wait_bar(f"Installing new {label} version...") as keep_alive,
self.tools.subprocess.Popen(
["xcrun", "simctl", "install", udid, self.binary_path(app)]
) as install_popen,
):
while (ret_code := install_popen.poll()) is None:
keep_alive.update()
time.sleep(0.25)
Expand Down
5 changes: 2 additions & 3 deletions src/briefcase/platforms/linux/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import subprocess
import sys
from pathlib import Path
from typing import List

from briefcase.commands.create import _is_local_requirement
from briefcase.commands.open import OpenCommand
Expand Down Expand Up @@ -134,7 +133,7 @@ def local_requirements_path(self, app):
def _install_app_requirements(
self,
app: AppConfig,
requires: List[str],
requires: list[str],
app_packages_path: Path,
):
"""Install requirements for the app with pip.
Expand Down Expand Up @@ -197,7 +196,7 @@ def _install_app_requirements(
app_packages_path=app_packages_path,
)

def _pip_requires(self, app: AppConfig, requires: List[str]):
def _pip_requires(self, app: AppConfig, requires: list[str]):
"""Convert the requirements list to an .deb project compatible format.

Any local file requirements are converted into a reference to the file generated
Expand Down
2 changes: 2 additions & 0 deletions src/briefcase/platforms/macOS/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ class macOSMixin:
platform = "macOS"
supported_host_os = {"Darwin"}
supported_host_os_reason = "macOS applications can only be built on macOS."
# 0.3.20 introduced a framework-based support package.
platform_target_version = "0.3.20"


class macOSCreateMixin(AppPackagesMergeMixin):
Expand Down
4 changes: 2 additions & 2 deletions src/briefcase/platforms/web/static.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import webbrowser
from http.server import SimpleHTTPRequestHandler, ThreadingHTTPServer
from pathlib import Path
from typing import Any, List
from typing import Any
from zipfile import ZipFile

from briefcase.console import Log
Expand Down Expand Up @@ -297,7 +297,7 @@ def run_app(
self,
app: AppConfig,
test_mode: bool,
passthrough: List[str],
passthrough: list[str],
host,
port,
open_browser,
Expand Down
3 changes: 1 addition & 2 deletions src/briefcase/platforms/windows/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import subprocess
import uuid
from pathlib import Path, PurePath
from typing import List
from zipfile import ZIP_DEFLATED, ZipFile

from briefcase.commands import CreateCommand, PackageCommand, RunCommand
Expand Down Expand Up @@ -131,7 +130,7 @@ def run_app(
self,
app: AppConfig,
test_mode: bool,
passthrough: List[str],
passthrough: list[str],
**kwargs,
):
"""Start the application.
Expand Down
2 changes: 1 addition & 1 deletion tests/commands/base/test_properties.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@


def test_briefcase_required_python_version(base_command):
assert base_command.briefcase_required_python_version == (3, 8)
assert base_command.briefcase_required_python_version == (3, 9)


def test_bundle_path(base_command, my_app, tmp_path):
Expand Down
9 changes: 4 additions & 5 deletions tests/integrations/base/test_tool_registry.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import inspect
import pkgutil
import sys
from typing import Dict, Set, Type

import pytest

import briefcase.integrations
from briefcase.integrations.base import ManagedTool, Tool, tool_registry


def integrations_modules() -> Set[str]:
def integrations_modules() -> set[str]:
"""All modules in ``briefcase.integrations`` irrespective of whether they are
defined in ``briefcase.integrations.__all__``"""
return {
Expand All @@ -19,23 +18,23 @@ def integrations_modules() -> Set[str]:
}


def tools_for_module(tool_module_name: str) -> Dict[str, Type[Tool]]:
def tools_for_module(tool_module_name: str) -> dict[str, type[Tool]]:
"""Return classes that subclass Tool in a module in ``briefcase.integrations``, e.g.
{"android_sdk": AndroidSDK}."""
return dict(
inspect.getmembers(
sys.modules[f"briefcase.integrations.{tool_module_name}"],
lambda klass: (
inspect.isclass(klass)
and not inspect.isabstract(klass)
and issubclass(klass, (Tool, ManagedTool))
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the only substantive logic change required by the version upgrade.

With the move of Sequence from typing.Sequence to collections.abc.Sequence, SubprocessArgsT now returns True from inspect.isclass(), but raises an error if you try to use it in issubclass. Adding an additional check for inspect.isabstract() avoids the error, and also allows removing the explicit reference to Tool and ManagedTool classes.

and klass not in {Tool, ManagedTool}
),
)
)


@pytest.fixture
def all_defined_tools() -> Set[Type[Tool]]:
def all_defined_tools() -> set[type[Tool]]:
"""All classes under ``briefcase.integrations`` that subclass Tool."""
return {
tool
Expand Down
2 changes: 1 addition & 1 deletion tests/platforms/linux/system/test_mixin__verify_python.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ def test_target_too_old(create_command, first_app_config):
with pytest.raises(
BriefcaseCommandError,
match=r"The system python3 version provided by somevendor:surprising "
r"is 3\.7\.16; Briefcase requires a minimum Python3 version of 3\.8\.",
r"is 3\.7\.16; Briefcase requires a minimum Python3 version of 3\.9\.",
):
create_command.verify_python(first_app_config)

Expand Down
3 changes: 3 additions & 0 deletions tests/platforms/macOS/app/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ def first_app_templated(first_app_config, tmp_path):
create_file(
tmp_path / "base_path/build/first-app/macos/app/briefcase.toml",
"""
[briefcase]
target_version = "0.3.20"

[paths]
app_packages_path="First App.app/Contents/Resources/app_packages"
support_path="First App.app/Contents/Frameworks"
Expand Down
Loading
Loading