Merge pull request #2404 from freakboy3742/arm64-testing
Add Python3.13 and iOS/macOS ARM64 testing to CI
This commit is contained in:
commit
c5887fe131
26 changed files with 112 additions and 57 deletions
65
.github/workflows/ci.yml
vendored
65
.github/workflows/ci.yml
vendored
|
|
@ -21,7 +21,7 @@ defaults:
|
|||
|
||||
# Cancel active CI runs for a PR before starting another run
|
||||
concurrency:
|
||||
group: ${{ github.ref }}
|
||||
group: ${{ github.workflow}}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
|
|
@ -60,18 +60,37 @@ jobs:
|
|||
- "winforms"
|
||||
|
||||
core:
|
||||
runs-on: ${{ matrix.platform }}-latest
|
||||
runs-on: ${{ matrix.platform }}
|
||||
needs: [pre-commit, towncrier, package]
|
||||
continue-on-error: ${{ matrix.experimental }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform: [ "macos", "ubuntu", "windows" ]
|
||||
python-version: [ "3.8", "3.9", "3.10", "3.11", "3.12" ]
|
||||
platform: [ "macos-12", "macos-14", "ubuntu-latest", "windows-latest" ]
|
||||
python-version: [ "3.8", "3.12", "3.13-dev" ]
|
||||
include:
|
||||
- experimental: false
|
||||
# - python-version: "3.13-dev"
|
||||
# experimental: true
|
||||
# Test Python 3.9-3.11 on Ubuntu only
|
||||
- platform: "ubuntu-latest"
|
||||
python-version: "3.9"
|
||||
experimental: false
|
||||
- platform: "ubuntu-latest"
|
||||
python-version: "3.10"
|
||||
experimental: false
|
||||
- platform: "ubuntu-latest"
|
||||
python-version: "3.11"
|
||||
experimental: false
|
||||
# Allow development 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"
|
||||
|
||||
# Pillow isn't available for Python 3.13 on Windows
|
||||
- platform: "windows-latest"
|
||||
python-version: "3.13-dev"
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.1
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
|
|
@ -144,22 +163,29 @@ jobs:
|
|||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
backend: [ "macOS", "windows", "linux", "android", "iOS" ]
|
||||
backend: [ "macOS-x86_64", "macOS-arm64", "windows", "linux", "android", "iOS" ]
|
||||
include:
|
||||
- pre-command:
|
||||
briefcase-run-prefix:
|
||||
briefcase-run-args:
|
||||
setup-python: true
|
||||
|
||||
- backend: macOS
|
||||
runs-on: macos-12
|
||||
- backend: "macOS-x86_64"
|
||||
platform: "macOS"
|
||||
runs-on: "macos-12"
|
||||
app-user-data-path: $HOME/Library/Application Support/org.beeware.toga.testbed
|
||||
|
||||
- backend: "macOS-arm64"
|
||||
platform: "macOS"
|
||||
runs-on: "macos-14"
|
||||
app-user-data-path: $HOME/Library/Application Support/org.beeware.toga.testbed
|
||||
|
||||
# We use a fixed Ubuntu version rather than `-latest` because at some point,
|
||||
# `-latest` will be updated, but it will be a soft changeover, which would cause
|
||||
# the system Python version to become inconsistent from run to run.
|
||||
- backend: linux
|
||||
runs-on: ubuntu-22.04
|
||||
- backend: "linux"
|
||||
platform: "linux"
|
||||
runs-on: "ubuntu-22.04"
|
||||
# The package list should be the same as in tutorial-0.rst, and the BeeWare
|
||||
# tutorial, plus blackbox to provide a window manager. We need a window
|
||||
# manager that is reasonably lightweight, honors full screen mode, and
|
||||
|
|
@ -185,17 +211,20 @@ jobs:
|
|||
setup-python: false # Use the system Python packages.
|
||||
app-user-data-path: $HOME/.local/share/testbed
|
||||
|
||||
- backend: windows
|
||||
runs-on: windows-latest
|
||||
- backend: "windows"
|
||||
platform: "windows"
|
||||
runs-on: "windows-latest"
|
||||
app-user-data-path: $HOME\AppData\Local\Tiberius Yak\Toga Testbed\Data
|
||||
|
||||
- backend: iOS
|
||||
runs-on: macos-12
|
||||
- backend: "iOS"
|
||||
platform: "iOS"
|
||||
runs-on: "macos-14"
|
||||
briefcase-run-args: ' -d "iPhone SE (3rd generation)"'
|
||||
app-user-data-path: $(xcrun simctl get_app_container booted org.beeware.toga.testbed data)/Documents
|
||||
|
||||
- backend: android
|
||||
runs-on: ubuntu-latest
|
||||
- backend: "android"
|
||||
platform: "android"
|
||||
runs-on: "ubuntu-latest"
|
||||
briefcase-run-args: " -d '{\"avd\":\"beePhone\",\"skin\":\"pixel_3a\"}' --Xemulator=-no-window --Xemulator=-no-snapshot --Xemulator=-no-audio --Xemulator=-no-boot-anim --shutdown-on-exit"
|
||||
pre-command: |
|
||||
# check if virtualization is supported...
|
||||
|
|
@ -230,7 +259,7 @@ jobs:
|
|||
- name: Test App
|
||||
working-directory: testbed
|
||||
timeout-minutes: 15
|
||||
run: ${{ matrix.briefcase-run-prefix }} briefcase run ${{ matrix.backend }} --test ${{ matrix.briefcase-run-args }}
|
||||
run: ${{ matrix.briefcase-run-prefix }} briefcase run ${{ matrix.platform }} --test ${{ matrix.briefcase-run-args }}
|
||||
|
||||
- name: Upload logs
|
||||
uses: actions/upload-artifact@v4.3.1
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ classifiers = [
|
|||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Programming Language :: Python :: 3.13",
|
||||
"Programming Language :: Python :: 3 :: Only",
|
||||
"Topic :: Software Development",
|
||||
"Topic :: Software Development :: User Interfaces",
|
||||
|
|
|
|||
1
changes/2383.bugfix.rst
Normal file
1
changes/2383.bugfix.rst
Normal file
|
|
@ -0,0 +1 @@
|
|||
Issues with running the testbed on macOS 14 (Sonoma) were resolved.
|
||||
1
changes/2404.feature.1.rst
Normal file
1
changes/2404.feature.1.rst
Normal file
|
|
@ -0,0 +1 @@
|
|||
Support for Python 3.13 was added.
|
||||
1
changes/2404.feature.2.rst
Normal file
1
changes/2404.feature.2.rst
Normal file
|
|
@ -0,0 +1 @@
|
|||
Toga's release processes now include automated testing on ARM64.
|
||||
|
|
@ -39,6 +39,7 @@ classifiers = [
|
|||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Programming Language :: Python :: 3.13",
|
||||
"Programming Language :: Python :: 3 :: Only",
|
||||
"Topic :: Software Development",
|
||||
"Topic :: Software Development :: User Interfaces",
|
||||
|
|
|
|||
|
|
@ -18,6 +18,11 @@ class TogaList(NSTableView):
|
|||
interface = objc_property(object, weak=True)
|
||||
impl = objc_property(object, weak=True)
|
||||
|
||||
@objc_method
|
||||
def didCloseMenu_withEvent_(self, menu, event) -> None:
|
||||
# When the menu closes, drop the reference to the menu object.
|
||||
self.impl._popup = None
|
||||
|
||||
@objc_method
|
||||
def menuForEvent_(self, event):
|
||||
if self.impl.primary_action_enabled or self.impl.secondary_action_enabled:
|
||||
|
|
@ -49,9 +54,12 @@ class TogaList(NSTableView):
|
|||
)
|
||||
secondary_action_item.tag = row
|
||||
|
||||
return popup
|
||||
else:
|
||||
return None
|
||||
popup = None
|
||||
|
||||
# Preserve a Python reference to the popup for testing purposes.
|
||||
self.impl._popup = popup
|
||||
return popup
|
||||
|
||||
@objc_method
|
||||
def primaryActionOnRow_(self, menuitem):
|
||||
|
|
|
|||
|
|
@ -99,7 +99,12 @@ class RefreshableClipView(NSClipView):
|
|||
argtypes=[NSPoint],
|
||||
)
|
||||
|
||||
if self.superview and self.superview.is_refreshing:
|
||||
# FIXME: This has been marked no-cover so that ARM64 testing can be enabled;
|
||||
# ARM64 CI can only run on Sonoma, and it looks like Sonoma has turned off
|
||||
# scroll elasticity by default, which prevents pull-to-refresh from working.
|
||||
# See Toga#2412 for details. If that ticket is closed, it should be possible
|
||||
# to remove this this no-cover.
|
||||
if self.superview and self.superview.is_refreshing: # pragma: no cover
|
||||
return NSMakePoint(
|
||||
constrained.x,
|
||||
max(
|
||||
|
|
|
|||
|
|
@ -179,9 +179,10 @@ class DetailedListProbe(SimpleProbe):
|
|||
while self.scroll_position < 0:
|
||||
await asyncio.sleep(0.01)
|
||||
|
||||
async def _perform_action(self, row, offset):
|
||||
async def _perform_action(self, row, index):
|
||||
point = self.row_position(row)
|
||||
# First click to show menu
|
||||
|
||||
# Click to show menu
|
||||
await self.mouse_event(
|
||||
NSEventType.RightMouseDown,
|
||||
point,
|
||||
|
|
@ -189,29 +190,17 @@ class DetailedListProbe(SimpleProbe):
|
|||
)
|
||||
await self.redraw("Action menu has been displayed")
|
||||
|
||||
# Pick a point a little to the right of the point where the menu was displayed,
|
||||
# and slightly lower (in reversed y coordinates) to select a menu item.
|
||||
point2 = NSPoint(point.x + 10, point.y - offset)
|
||||
await self.mouse_event(
|
||||
NSEventType.LeftMouseDown,
|
||||
point2,
|
||||
delay=0.1,
|
||||
)
|
||||
await self.mouse_event(
|
||||
NSEventType.LeftMouseUp,
|
||||
point2,
|
||||
delay=0.1,
|
||||
)
|
||||
popup = self.impl._popup
|
||||
if popup:
|
||||
popup.performActionForItemAtIndex(index)
|
||||
popup.cancelTracking()
|
||||
|
||||
# Wait until the popup menu is fully disposed.
|
||||
while self.impl._popup is not None:
|
||||
await self.redraw("Action has been selected", delay=0.1)
|
||||
|
||||
async def perform_primary_action(self, row, active=True):
|
||||
# 10px is enough to select the first menu item. It doesn't matter whether the
|
||||
# action is active or not; if the action is inactive, it will either press the
|
||||
# wrong action, or press empty space.
|
||||
await self._perform_action(row, 10)
|
||||
await self._perform_action(row, 0)
|
||||
|
||||
async def perform_secondary_action(self, row, active=True):
|
||||
# 30px is enough to select the second menu item. However the secondary action
|
||||
# will be in position 1 on the menu if the primary action is disabled. It
|
||||
# doesn't matter whether the action is active or not; if the action is inactive,
|
||||
# it will either press the wrong action, or press empty space.
|
||||
await self._perform_action(row, 30 if self.impl.primary_action_enabled else 10)
|
||||
await self._perform_action(row, 1 if self.impl.primary_action_enabled else 0)
|
||||
|
|
|
|||
|
|
@ -46,8 +46,5 @@ class SelectionProbe(SimpleProbe):
|
|||
# Use a short delaly instead.
|
||||
await self.mouse_event(NSEventType.LeftMouseDown, point, delay=0.1)
|
||||
|
||||
# macOS coordinate systems are backwards, so to select the item *above*
|
||||
# the current selection, you need to *add* height.
|
||||
point.y = point.y + self.height
|
||||
await self.mouse_event(NSEventType.LeftMouseDown, point, delay=0.1)
|
||||
await self.mouse_event(NSEventType.LeftMouseUp, point, delay=0.1)
|
||||
self.native.menu.performActionForItemAtIndex(1)
|
||||
self.native.menu.cancelTracking()
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ classifiers = [
|
|||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Programming Language :: Python :: 3.13",
|
||||
"Programming Language :: Python :: 3 :: Only",
|
||||
"Topic :: Software Development",
|
||||
"Topic :: Software Development :: User Interfaces",
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ classifiers = [
|
|||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Programming Language :: Python :: 3.13",
|
||||
"Programming Language :: Python :: 3 :: Only",
|
||||
"Topic :: Software Development",
|
||||
"Topic :: Software Development :: User Interfaces",
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ classifiers = [
|
|||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Programming Language :: Python :: 3.13",
|
||||
"Programming Language :: Python :: 3 :: Only",
|
||||
"Topic :: Software Development",
|
||||
"Topic :: Software Development :: User Interfaces",
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ classifiers = [
|
|||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Programming Language :: Python :: 3.13",
|
||||
"Programming Language :: Python :: 3 :: Only",
|
||||
"Topic :: Software Development",
|
||||
"Topic :: Software Development :: User Interfaces",
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ classifiers = [
|
|||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Programming Language :: Python :: 3.13",
|
||||
"Programming Language :: Python :: 3 :: Only",
|
||||
"Topic :: Software Development",
|
||||
"Topic :: Software Development :: User Interfaces",
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import asyncio
|
||||
import platform
|
||||
import os
|
||||
|
||||
from rubicon.objc.api import Block
|
||||
from rubicon.objc.api import Block, ObjCClass
|
||||
|
||||
from toga_iOS.libs import (
|
||||
NSIndexPath,
|
||||
|
|
@ -13,6 +13,8 @@ from toga_iOS.libs import (
|
|||
|
||||
from .base import SimpleProbe, UIControlEventValueChanged
|
||||
|
||||
UIDevice = ObjCClass("UIDevice")
|
||||
|
||||
|
||||
class DetailedListProbe(SimpleProbe):
|
||||
native_class = UITableView
|
||||
|
|
@ -50,11 +52,17 @@ class DetailedListProbe(SimpleProbe):
|
|||
@property
|
||||
def max_scroll_position(self):
|
||||
max_value = int(self.native.contentSize.height - self.native.frame.size.height)
|
||||
# The max value is a little higher on iOS 17.
|
||||
# Not sure where the 34 extra pixels are coming from. It appears to be
|
||||
# a constant, independent of the number of rows of data.
|
||||
if int(platform.release().split(".")[0]) >= 17:
|
||||
# The max value is a dependent on the device; devices that don't have a physical
|
||||
# button report as being a little larger. A physical device will give you the
|
||||
# model identifier as part of UIDevice.currentDevice.model; however, simulators
|
||||
# return "iPhone" as the model, so we need to check the environment as well to
|
||||
# reliably get the device identifier. "iPhone14,6" is an iPhone SE 3rd edition.
|
||||
# As of Feb 2023, it's the only device currently sold that has a physical
|
||||
# button.
|
||||
model = os.getenv("SIMULATOR_MODEL_IDENTIFIER", UIDevice.currentDevice.model)
|
||||
if model != "iPhone14,6":
|
||||
max_value += 34
|
||||
|
||||
return max(0, max_value)
|
||||
|
||||
@property
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ classifiers = [
|
|||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Programming Language :: Python :: 3.13",
|
||||
"Programming Language :: Python :: 3 :: Only",
|
||||
"Topic :: Software Development",
|
||||
"Topic :: Software Development :: User Interfaces",
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ classifiers = [
|
|||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Programming Language :: Python :: 3.13",
|
||||
"Programming Language :: Python :: 3 :: Only",
|
||||
"Topic :: Software Development",
|
||||
"Topic :: Software Development :: User Interfaces",
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ classifiers = [
|
|||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Programming Language :: Python :: 3.13",
|
||||
"Programming Language :: Python :: 3 :: Only",
|
||||
"Topic :: Software Development",
|
||||
"Topic :: Software Development :: User Interfaces",
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ classifiers = [
|
|||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Programming Language :: Python :: 3.13",
|
||||
"Programming Language :: Python :: 3 :: Only",
|
||||
"Topic :: Software Development",
|
||||
"Topic :: Software Development :: User Interfaces",
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ classifiers = [
|
|||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Programming Language :: Python :: 3.13",
|
||||
"Programming Language :: Python :: 3 :: Only",
|
||||
"Topic :: Software Development",
|
||||
"Topic :: Software Development :: User Interfaces",
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ classifiers = [
|
|||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Programming Language :: Python :: 3.13",
|
||||
"Programming Language :: Python :: 3 :: Only",
|
||||
"Topic :: Software Development",
|
||||
"Topic :: Software Development :: User Interfaces",
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ classifiers = [
|
|||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Programming Language :: Python :: 3.13",
|
||||
"Programming Language :: Python :: 3 :: Only",
|
||||
"Topic :: Software Development",
|
||||
"Topic :: Software Development :: User Interfaces",
|
||||
|
|
|
|||
2
tox.ini
2
tox.ini
|
|
@ -7,7 +7,7 @@ extend-ignore =
|
|||
E203,
|
||||
|
||||
# The leading comma generates the "py" environment.
|
||||
[testenv:py{,38,39,310,311,312}]
|
||||
[testenv:py{,38,39,310,311,312,313}]
|
||||
skip_install = True
|
||||
setenv =
|
||||
TOGA_BACKEND = toga_dummy
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ classifiers = [
|
|||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Programming Language :: Python :: 3.13",
|
||||
"Programming Language :: Python :: 3 :: Only",
|
||||
"Topic :: Software Development",
|
||||
"Topic :: Software Development :: User Interfaces",
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ classifiers = [
|
|||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Programming Language :: Python :: 3.13",
|
||||
"Programming Language :: Python :: 3 :: Only",
|
||||
"Topic :: Software Development",
|
||||
"Topic :: Software Development :: User Interfaces",
|
||||
|
|
|
|||
Loading…
Reference in a new issue