diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a87e69599..6f4fc563b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -170,7 +170,7 @@ jobs: strategy: fail-fast: false matrix: - framework: [ "toga", "pyside6", "ppb", "pygame" ] + framework: [ "toga", "pyside6", "pygame" ] runner-os: [ "macos-12", "macos-14", "ubuntu-22.04", "windows-latest" ] verify-apps: @@ -189,5 +189,5 @@ jobs: strategy: fail-fast: false matrix: - framework: [ "toga", "pyside6", "ppb", "pygame" ] + framework: [ "toga", "pyside6", "pygame" ] runner-os: [ "macos-12", "macos-14", "ubuntu-22.04", "windows-latest" ] diff --git a/automation/pyproject.toml b/automation/pyproject.toml index 5260410d5..9c01c0871 100644 --- a/automation/pyproject.toml +++ b/automation/pyproject.toml @@ -19,7 +19,6 @@ dynamic = ["version", "dependencies"] "Toga Automation" = "automation.bootstraps.toga:TogaAutomationBootstrap" "PySide6 Automation" = "automation.bootstraps.pyside6:PySide6AutomationBootstrap" "Pygame Automation" = "automation.bootstraps.pygame:PygameAutomationBootstrap" -"PursuedPyBear Automation" = "automation.bootstraps.pursuedpybear:PursuedPyBearAutomationBootstrap" [tool.setuptools_scm] root = "../" diff --git a/automation/src/automation/bootstraps/pursuedpybear.py b/automation/src/automation/bootstraps/pursuedpybear.py deleted file mode 100644 index 091178efa..000000000 --- a/automation/src/automation/bootstraps/pursuedpybear.py +++ /dev/null @@ -1,50 +0,0 @@ -from automation.bootstraps import BRIEFCASE_EXIT_SUCCESS_SIGNAL, EXIT_SUCCESS_NOTIFY -from briefcase.bootstraps import PursuedPyBearGuiBootstrap - - -class PursuedPyBearAutomationBootstrap(PursuedPyBearGuiBootstrap): - def app_source(self): - return f"""\ -import importlib.metadata -import os -import sys - -import ppb - - -class {{{{ cookiecutter.class_name }}}}(ppb.Scene): - def __init__(self, **props): - super().__init__(**props) - self.updates: int = 0 - - def on_update(self, event, signal): - self.updates += 1 - # quit after 2 seconds since on_update is run 60 times/second - if self.updates > 120: - print("{EXIT_SUCCESS_NOTIFY}") - print("{BRIEFCASE_EXIT_SUCCESS_SIGNAL}") - signal(ppb.events.Quit()) - - -def main(): - # Linux desktop environments use an app's .desktop file to integrate the app - # in to their application menus. The .desktop file of this app will include - # the StartupWMClass key, set to app's formal name. This helps associate the - # app's windows to its menu item. - # - # For association to work, any windows of the app must have WMCLASS property - # set to match the value set in app's desktop file. For PPB, this is set - # using the SDL_VIDEO_X11_WMCLASS environment variable. - - # Find the name of the module that was used to start the app - app_module = sys.modules["__main__"].__package__ - # Retrieve the app's metadata - metadata = importlib.metadata.metadata(app_module) - - os.environ["SDL_VIDEO_X11_WMCLASS"] = metadata["Formal-Name"] - - ppb.run( - starting_scene={{{{ cookiecutter.class_name }}}}, - title=metadata["Formal-Name"], - ) -""" diff --git a/changes/1834.removal.rst b/changes/1834.removal.rst new file mode 100644 index 000000000..b4b7d041e --- /dev/null +++ b/changes/1834.removal.rst @@ -0,0 +1 @@ +Migrated PursuedPyBear bootstrap to the PursuedPyBear project. diff --git a/pyproject.toml b/pyproject.toml index 13b1038ef..8e1d3cbcb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -133,7 +133,6 @@ briefcase = "briefcase.__main__:main" [project.entry-points."briefcase.bootstraps"] Toga = "briefcase.bootstraps.toga:TogaGuiBootstrap" PySide6 = "briefcase.bootstraps.pyside6:PySide6GuiBootstrap" -PursuedPyBear = "briefcase.bootstraps.pursuedpybear:PursuedPyBearGuiBootstrap" Pygame = "briefcase.bootstraps.pygame:PygameGuiBootstrap" [project.entry-points."briefcase.platforms"] diff --git a/src/briefcase/bootstraps/__init__.py b/src/briefcase/bootstraps/__init__.py index c344e33de..239fcf095 100644 --- a/src/briefcase/bootstraps/__init__.py +++ b/src/briefcase/bootstraps/__init__.py @@ -1,5 +1,4 @@ from briefcase.bootstraps.base import BaseGuiBootstrap # noqa: F401 -from briefcase.bootstraps.pursuedpybear import PursuedPyBearGuiBootstrap # noqa: F401 from briefcase.bootstraps.pygame import PygameGuiBootstrap # noqa: F401 from briefcase.bootstraps.pyside6 import PySide6GuiBootstrap # noqa: F401 from briefcase.bootstraps.toga import TogaGuiBootstrap # noqa: F401 diff --git a/src/briefcase/bootstraps/pursuedpybear.py b/src/briefcase/bootstraps/pursuedpybear.py deleted file mode 100644 index 9f968db4b..000000000 --- a/src/briefcase/bootstraps/pursuedpybear.py +++ /dev/null @@ -1,167 +0,0 @@ -from briefcase.bootstraps.base import BaseGuiBootstrap - - -class PursuedPyBearGuiBootstrap(BaseGuiBootstrap): - display_name_annotation = "does not support iOS/Android deployment" - - def app_source(self): - return """\ -import importlib.metadata -import os -import sys - -import ppb - - -class {{ cookiecutter.class_name }}(ppb.Scene): - def __init__(self, **props): - super().__init__(**props) - - # Add sprites and details to your scene here - - -def main(): - # Linux desktop environments use an app's .desktop file to integrate the app - # in to their application menus. The .desktop file of this app will include - # the StartupWMClass key, set to app's formal name. This helps associate the - # app's windows to its menu item. - # - # For association to work, any windows of the app must have WMCLASS property - # set to match the value set in app's desktop file. For PPB, this is set - # using the SDL_VIDEO_X11_WMCLASS environment variable. - - # Find the name of the module that was used to start the app - app_module = sys.modules["__main__"].__package__ - # Retrieve the app's metadata - metadata = importlib.metadata.metadata(app_module) - - os.environ["SDL_VIDEO_X11_WMCLASS"] = metadata["Formal-Name"] - - ppb.run( - starting_scene={{ cookiecutter.class_name }}, - title=metadata["Formal-Name"], - ) -""" - - def pyproject_table_briefcase_app_extra_content(self): - return """ -requires = [ - "ppb~=3.2.0", -] -test_requires = [ -{% if cookiecutter.test_framework == "pytest" %} - "pytest", -{% endif %} -] -""" - - def pyproject_table_macOS(self): - return """\ -universal_build = true -requires = [ - "std-nslog~=1.0.0", -] -""" - - def pyproject_table_linux(self): - return """\ -requires = [ -] -""" - - def pyproject_table_linux_system_debian(self): - return """\ -system_requires = [ -] - -system_runtime_requires = [ - "libsdl2-2.0-0", - "libsdl2-mixer-2.0-0", - "libsdl2-image-2.0-0", - "libsdl2-gfx-1.0-0", - "libsdl2-ttf-2.0-0", -] -""" - - def pyproject_table_linux_system_rhel(self): - return """\ -system_requires = [ -] - -system_runtime_requires = [ - "SDL2", - "SDL2_ttf", - "SDL2_image", - "SDL2_gfx", - "SDL2_mixer", - "libmodplug", -] -""" - - def pyproject_table_linux_system_suse(self): - return """\ -system_requires = [ -] - -system_runtime_requires = [ - "SDL2", - "SDL2_gfx", - "SDL2_ttf", - "SDL2_image", - "SDL2_mixer", - "libmodplug1", -] -""" - - def pyproject_table_linux_system_arch(self): - return """\ -system_requires = [ -] - -system_runtime_requires = [ - "sdl2", - "sdl2_ttf", - "sdl2_image", - "sdl2_gfx", - "sdl2_mixer", -] -""" - - def pyproject_table_linux_appimage(self): - return """\ -manylinux = "manylinux_2_28" - -system_requires = [ -] - -linuxdeploy_plugins = [ -] -""" - - def pyproject_table_linux_flatpak(self): - return """\ -flatpak_runtime = "org.freedesktop.Platform" -flatpak_runtime_version = "23.08" -flatpak_sdk = "org.freedesktop.Sdk" -""" - - def pyproject_table_windows(self): - return """\ -requires = [ -] -""" - - def pyproject_table_iOS(self): - return """\ -supported = false -""" - - def pyproject_table_android(self): - return """\ -supported = false -""" - - def pyproject_table_web(self): - return """\ -supported = false -""" diff --git a/src/briefcase/commands/new.py b/src/briefcase/commands/new.py index 1a8e6dffa..2bb7c74be 100644 --- a/src/briefcase/commands/new.py +++ b/src/briefcase/commands/new.py @@ -653,9 +653,8 @@ def _gui_bootstrap_choices(self, bootstraps): # Sort the options alphabetically first ordered = OrderedDict(sorted(bootstraps.items())) - # Ensure the first 5 options are: Toga, PySide6, PursuedPyBear, Pygame + # Ensure the first 5 options are: Toga, PySide6, Pygame ordered.move_to_end("Pygame", last=False) - ordered.move_to_end("PursuedPyBear", last=False) ordered.move_to_end("PySide6", last=False) ordered.move_to_end("Toga", last=False) diff --git a/tests/commands/new/test_build_context.py b/tests/commands/new/test_build_context.py index 2fd7b49e7..dbbe3f5a8 100644 --- a/tests/commands/new/test_build_context.py +++ b/tests/commands/new/test_build_context.py @@ -4,7 +4,6 @@ import briefcase.commands.new from briefcase.bootstraps import ( - PursuedPyBearGuiBootstrap, PygameGuiBootstrap, PySide6GuiBootstrap, TogaGuiBootstrap, @@ -16,7 +15,6 @@ def mock_builtin_bootstraps(): return { "Toga": TogaGuiBootstrap, "PySide6": PySide6GuiBootstrap, - "PursuedPyBear": PursuedPyBearGuiBootstrap, "Pygame": PygameGuiBootstrap, } @@ -428,178 +426,6 @@ def main(): ) -def test_question_sequence_pursuedpybear(new_command): - """Questions are asked, a context is constructed.""" - - # Prime answers for all the questions. - new_command.input.values = [ - "My Application", # formal name - "", # app name - accept the default - "org.beeware", # bundle ID - "My Project", # project name - "Cool stuff", # description - "Grace Hopper", # author - "grace@navy.mil", # author email - "https://navy.mil/myapplication", # URL - "4", # license - "3", # PursuedPyBear GUI toolkit - ] - - context = new_command.build_context( - project_overrides={}, - ) - - assert context == dict( - app_name="myapplication", - author="Grace Hopper", - author_email="grace@navy.mil", - bundle="org.beeware", - class_name="MyApplication", - description="Cool stuff", - formal_name="My Application", - license="GNU General Public License v2 (GPLv2)", - module_name="myapplication", - source_dir="src/myapplication", - test_source_dir="tests", - project_name="My Project", - url="https://navy.mil/myapplication", - app_source="""\ -import importlib.metadata -import os -import sys - -import ppb - - -class {{ cookiecutter.class_name }}(ppb.Scene): - def __init__(self, **props): - super().__init__(**props) - - # Add sprites and details to your scene here - - -def main(): - # Linux desktop environments use an app's .desktop file to integrate the app - # in to their application menus. The .desktop file of this app will include - # the StartupWMClass key, set to app's formal name. This helps associate the - # app's windows to its menu item. - # - # For association to work, any windows of the app must have WMCLASS property - # set to match the value set in app's desktop file. For PPB, this is set - # using the SDL_VIDEO_X11_WMCLASS environment variable. - - # Find the name of the module that was used to start the app - app_module = sys.modules["__main__"].__package__ - # Retrieve the app's metadata - metadata = importlib.metadata.metadata(app_module) - - os.environ["SDL_VIDEO_X11_WMCLASS"] = metadata["Formal-Name"] - - ppb.run( - starting_scene={{ cookiecutter.class_name }}, - title=metadata["Formal-Name"], - ) -""", - pyproject_table_briefcase_app_extra_content=""" -requires = [ - "ppb~=3.2.0", -] -test_requires = [ -{% if cookiecutter.test_framework == "pytest" %} - "pytest", -{% endif %} -] -""", - pyproject_table_macOS="""\ -universal_build = true -requires = [ - "std-nslog~=1.0.0", -] -""", - pyproject_table_linux="""\ -requires = [ -] -""", - pyproject_table_linux_system_debian="""\ -system_requires = [ -] - -system_runtime_requires = [ - "libsdl2-2.0-0", - "libsdl2-mixer-2.0-0", - "libsdl2-image-2.0-0", - "libsdl2-gfx-1.0-0", - "libsdl2-ttf-2.0-0", -] -""", - pyproject_table_linux_system_rhel="""\ -system_requires = [ -] - -system_runtime_requires = [ - "SDL2", - "SDL2_ttf", - "SDL2_image", - "SDL2_gfx", - "SDL2_mixer", - "libmodplug", -] -""", - pyproject_table_linux_system_suse="""\ -system_requires = [ -] - -system_runtime_requires = [ - "SDL2", - "SDL2_gfx", - "SDL2_ttf", - "SDL2_image", - "SDL2_mixer", - "libmodplug1", -] -""", - pyproject_table_linux_system_arch="""\ -system_requires = [ -] - -system_runtime_requires = [ - "sdl2", - "sdl2_ttf", - "sdl2_image", - "sdl2_gfx", - "sdl2_mixer", -] -""", - pyproject_table_linux_appimage="""\ -manylinux = "manylinux_2_28" - -system_requires = [ -] - -linuxdeploy_plugins = [ -] -""", - pyproject_table_linux_flatpak="""\ -flatpak_runtime = "org.freedesktop.Platform" -flatpak_runtime_version = "23.08" -flatpak_sdk = "org.freedesktop.Sdk" -""", - pyproject_table_windows="""\ -requires = [ -] -""", - pyproject_table_iOS="""\ -supported = false -""", - pyproject_table_android="""\ -supported = false -""", - pyproject_table_web="""\ -supported = false -""", - ) - - def test_question_sequence_pygame(new_command): """Questions are asked, a context is constructed.""" @@ -614,7 +440,7 @@ def test_question_sequence_pygame(new_command): "grace@navy.mil", # author email "https://navy.mil/myapplication", # URL "4", # license - "4", # Pygame GUI toolkit + "3", # Pygame GUI toolkit ] context = new_command.build_context( @@ -773,7 +599,7 @@ def test_question_sequence_none(new_command): "grace@navy.mil", # author email "https://navy.mil/myapplication", # URL "4", # license - "5", # None + "4", # None ] context = new_command.build_context( @@ -926,7 +752,7 @@ def test_question_sequence_with_bad_bootstrap_override( # Prime answers for none of the questions. new_command.input.values = [ - "6", # None + "5", # None ] class GuiBootstrap: @@ -1240,7 +1066,7 @@ def platform(self): "grace@navy.mil", # author email "https://navy.mil/myapplication", # URL "4", # license - "5", # Custom GUI bootstrap + "4", # Custom GUI bootstrap ] context = new_command.build_context(project_overrides={}) @@ -1306,7 +1132,7 @@ def platform(self): "grace@navy.mil", # author email "https://navy.mil/myapplication", # URL "4", # license - "5", # Custom GUI bootstrap + "4", # Custom GUI bootstrap ] context = new_command.build_context(project_overrides={})