Skip to content

Add guidance for third-party bootstraps#2640

Open
moondial-pal wants to merge 35 commits intobeeware:mainfrom
moondial-pal:briefcase-bootstraps
Open

Add guidance for third-party bootstraps#2640
moondial-pal wants to merge 35 commits intobeeware:mainfrom
moondial-pal:briefcase-bootstraps

Conversation

@moondial-pal
Copy link
Copy Markdown
Contributor

Add an “Other frameworks…” option to the GUI bootstrap selection shown during
briefcase new.

Users can now explicitly select a community provided GUI framework option,
receive guidance about support expectations, and exit cleanly with next steps.

Fixes #2342

PR Checklist:

  • All new features have been tested
  • All new features have been documented
  • I have read the CONTRIBUTING.md file
  • I will abide by the code of conduct

@kattni
Copy link
Copy Markdown
Contributor

kattni commented Jan 25, 2026

Hello! Thank you for the contribution. The majority of the failing tests are due to an issue unrelated to your PR. The fix has been submitted and merged into main. You'll need to rebase or merge main to get to a point where you can see which tests are failing related to your contribution. Please let us know if you need any help with that process. Thanks!

Please be aware that you'll also need to upgrade rich in your local environment or the tests will continue to fail locally for you

Copy link
Copy Markdown
Member

@freakboy3742 freakboy3742 left a comment

Choose a reason for hiding this comment

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

Thanks for the PR; however, from the look of it, this doesn't actually address the problem that was described in the ticket.

This PR does add another menu item for "other frameworks"; however, it doesn't provide any real information beyond that. The menu prompt says "select to see options"; the implication of this is that you will... see options. As currently implemented, all you get is text that tells you other options might exist, which is not really any better than the prompt that is already provided.

The purpose of the feature request is to help resolve the discovery issue - to let people know that there are other options they could install, and how to install them.

For example, right now, Toga Positron is a plugin option. If you select option 6, that option should be listed; if you select it, you should be told to install toga-positron.

If toga-positron is installed, that option shouldn't appear in "other options".

The expectation would be that we'd accept contributions from third-parties that want their plugins listed, and we prime that list with the plugins that are already listed in documentation.

Let me know if you need any more clarification on this.

@moondial-pal moondial-pal marked this pull request as draft January 27, 2026 02:24
@moondial-pal
Copy link
Copy Markdown
Contributor Author

Understood, thanks for the feedback.
I'll continue working on this to add a secondary menu that lists known third-party bootstrap plugins, provides install instructions, and hides options that are already installed. I’ll follow up once I have something closer to that behavior.

@mhsmith mhsmith changed the title Briefcase bootstraps Add guidance for third-party bootstraps Jan 28, 2026
moondial-pal and others added 9 commits January 28, 2026 18:30
- Insert "Other frameworks…" as second-to-last bootstrap choice
- Handle sentinel selection with disclaimer and guidance
- Abort cleanly instead of indexing into non-existent bootstrap
- Verify selecting Other frameworks aborts as expected
- Update nemeric selections to reflect new menu option
Update the test to assert the correct type and compute the menu
dynamically to avoid odering assumptions.
- Installed plugins will affect the GUI bootstrap menu
- Update the test to select the sentinel entry by value not by hard-coded
  position
@moondial-pal moondial-pal marked this pull request as ready for review January 29, 2026 02:57
@moondial-pal
Copy link
Copy Markdown
Contributor Author

@kattni Thanks for the heads up! I’ve rebased the branch onto the current main as suggested and confirmed the full test suite passes locally. I’m still seeing CI failures on the PR, so I’m taking another look in case there’s anything else I missed, please let me know if you spot anything on your end.

@moondial-pal
Copy link
Copy Markdown
Contributor Author

It’s my understanding that community GUI bootstraps are considered installed
only if they expose a briefcase.bootstraps entry point. I may be missing
something, but PPB does not appear to publish such an entry point currently.

I tested both PPB and pygame-ce locally: pygame-ce was detected as installed
and correctly hidden from the community submenu, while PPB continued to
appear. I’ve left PPB in the list because it is documented as a known
community GUI bootstrap.

@freakboy3742
Copy link
Copy Markdown
Member

It’s my understanding that community GUI bootstraps are considered installed only if they expose a briefcase.bootstraps entry point. I may be missing something, but PPB does not appear to publish such an entry point currently.

I tested both PPB and pygame-ce locally: pygame-ce was detected as installed and correctly hidden from the community submenu, while PPB continued to appear. I’ve left PPB in the list because it is documented as a known community GUI bootstrap.

Your understanding is correct; and yes, it looks like PPB isn't actually publishing a bootstrap at this point.

I'll need to follow up with the PPB team; IIRC, the entry was added during (or related to activity at) PyCon US sprints; it's possible the PR wasn't finalized or merged. If it doesn't work, there's no point leaving it on the list.

@moondial-pal
Copy link
Copy Markdown
Contributor Author

Got it. I'll go ahead and remove ppb from the list for this PR.
I can submit an issue/pr to update the docs for third-party plugins to remove ppb from there as well, or should we leave that as is?

@freakboy3742
Copy link
Copy Markdown
Member

Got it. I'll go ahead and remove ppb from the list for this PR. I can submit an issue/pr to update the docs for third-party plugins to remove ppb from there as well, or should we leave that as is?

Might as well remove it from the docs as well - if it doesn't work, there's no point highlighting it.

@moondial-pal
Copy link
Copy Markdown
Contributor Author

moondial-pal commented Feb 2, 2026

@freakboy3742 Sorry I fat fingered the request for review. I had not made the requested change yet. Apologies.
I think that was the previous change request from the initial PR submission.
I believe the requested changes are now fully addressed:

  • Secondary submenu for third-party GUI bootstraps
  • Install guidance shown
  • Installed plugins hidden
  • PPB removed from the list

Thanks again for the guidance, ready for re-review when you are.

Copy link
Copy Markdown
Member

@freakboy3742 freakboy3742 left a comment

Choose a reason for hiding this comment

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

Generally looks good; the review comments are mostly about user ergonomics, and the exact presentation of error message.

The one bigger question is about the overall workflow. The GUI framework question has always been the last question; however, with this new question, it means that you answer all the questions about your app... and then get told to re-run briefcase new. I think it would make sense to make the framework question the first question, so that the user doesn't lose anything if the wizard needs to be re-run.

Comment on lines +484 to +486
raise BriefcaseCommandError(
"Install a community GUI bootstrap plugin and re-run `briefcase new`."
)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Raising BriefcaseCommandError means the command exits as an error, generating a log. Selecting a different GUI framework is "normal behavior", so it shouldn't be generating a log; and while we need to draw the attention of the user, the user hasn't done anything wrong, so it shouldn't surface in red as an error.

I'd suggest once the user selects a plugin, the text should be displayed as a warning, and read something like:

Pygame-ce is provided by a community plugin. To use this plugin, run:

    python -m pip install pygame-ce

then re-run `briefcase new`.

I'd also suggest that the output should all be part of the "other frameworks menu" code - if only because the case where you have installed all known plugins, you currently get an "there are no additional plugins; please install a plugin" message.

Comment on lines +522 to +523
for name in reversed(("Toga", "PySide6", "Pygame")):
ordered.move_to_end(name, last=False)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why this change? You've taken three lines of explicit code, and used a pre-computed list... which is then processed into reverse order. Why not provide the list in reversed order?

Comment on lines +556 to +557
self.console.warning()
self.console.warning(
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We generally don't use console commands as "one per line of output" - we combine them all into a single call that includes any required newlines.

@freakboy3742
Copy link
Copy Markdown
Member

Also - we generally don't rebase PRs unless something catastrophic goes wrong. We use squash commits, so multiple merge commits or noisy "no really fixed this time" commits in a PR won't appear in the final product; and when you rebase, any comments on rebased lines get lost.

@moondial-pal
Copy link
Copy Markdown
Contributor Author

I really appreciate the patience and time taken for guidance on these reviews.
I'll work on these suggestions/comments.

@moondial-pal
Copy link
Copy Markdown
Contributor Author

Marking this as draft while I finish simplifying the selection logic and aligning the tests with the updated behavior. I’ll move it back to ready once everything is clean and passing.

@moondial-pal
Copy link
Copy Markdown
Contributor Author

Working on CI fixes.

@freakboy3742
Copy link
Copy Markdown
Member

Apologies for the issues with the docs builds - we launched a new version of the website on Friday, and we've been shaking out loose links ever since.

I think we've got most of them sorted out at this point; but some of the docs build problems require merging with main, so if you're seeing problems, try that as a fix first. If you're still seeing problems, let us know and we can dig into the problem for you.

Merging upstream main to update branch with changes to docs.
@moondial-pal moondial-pal marked this pull request as ready for review March 6, 2026 01:28
@moondial-pal
Copy link
Copy Markdown
Contributor Author

Hi @freakboy3742, this is ready for review. I believe I have addressed your feedback and the diff is larger than usual given the new community framework wizard behavior we discussed. Let me know if anything needs adjusting.

@freakboy3742
Copy link
Copy Markdown
Member

@moondial-pal Thanks for the update - I hope to be able to give this a review in the next couple of days.

Copy link
Copy Markdown
Member

@freakboy3742 freakboy3742 left a comment

Choose a reason for hiding this comment

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

Thanks for those updates. I think the broad structure is getting closer; but there's some things that are still odd about data structure use, and the specifics of the experience the user has when they run the wizard.


# A plugin is treated as "installed" if its distribution package is installed,
# regardless of how many Briefcase entry points it provides.
KNOWN_COMMUNITY_PLUGINS: ClassVar[list[dict[str, str]]] = [
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This data structure is only ever accessed by iteration, or as lookup for a package name. Why not store it as a dictionary keyed by package name?

Comment on lines +587 to +588
if plugin.get("description")
else plugin["display_name"]
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We're in control of the list of plugins here, so we can guarantee they all have display names and descriptions.

Comment on lines 643 to 644
bootstrap_class = self.select_bootstrap(project_overrides)
context = self.build_app_context(project_overrides)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This changes the order of questions - which is what we wanted - but doesn't address the fact that the first question on the "build_app_context" question list starts "First, we need ...". The question text will need to be tweaked.

if not is_package_installed(plugin["package"])
]

if not not_installed_plugins:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

not not_installed is a bit awkward; not uninstalled... would read a bit better.

Comment on lines +531 to +547
preferred = ["Toga", "PySide6", "Pygame", "Console"]

# Sort framework names (excluding sentinel options).
ordered = sorted(
name
for name in bootstrap_names
if name not in (self.OTHER_FRAMEWORKS, "None")
)

# Ensure the first 3 options are: Toga, PySide6, Pygame
ordered.move_to_end("Pygame", last=False)
ordered.move_to_end("PySide6", last=False)
ordered.move_to_end("Toga", last=False)
# Pull preferred items to the front (in explicit order) if present.
ordered = [name for name in preferred if name in ordered] + [
name for name in ordered if name not in preferred
]

# Option None should always be last
ordered.move_to_end("None")
ordered.append(self.OTHER_FRAMEWORKS)
if "None" in bootstrap_names:
ordered.append("None")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is now the third time I've provided this feedback (Ref 1, ref 2): why are you changing this section of code?

Unless I'm missing something, the existing code does everything that is needed, and is a lot less complicated. The updated implementation involves multiple sorts, appended lists, and optional comparisons... when all we need is what is already here - sort the inputs, ensure 3 specific options are first, and "Other" and "None" are last. This doesn't require a complex sorting. The code that is already here does everything that is needed.

If there's a something that I'm missing here, please let me know - but otherwise, please revert this to the original code. It works and is easy to understand. It doesn't need to be fixed unless there is actually something wrong with it.

@moondial-pal
Copy link
Copy Markdown
Contributor Author

Understood, I'll revert the ordering section and address the other feedback. Thanks for your patience.

@moondial-pal
Copy link
Copy Markdown
Contributor Author

Checking what may have caused failures on my end.

@moondial-pal
Copy link
Copy Markdown
Contributor Author

moondial-pal commented Mar 23, 2026

The pre-commit checks passed locally but the CI caught a line length issue among other things. Circling back to make sure test coverage is 100%.

Co-authored-by: Russell Keith-Magee <russell@keith-magee.com>
@moondial-pal
Copy link
Copy Markdown
Contributor Author

Great point, I can see how that reads ambiguously. Working on getting the platform tests green...I think my dev environment got a bit tangled working across two machines.

Copy link
Copy Markdown
Member

@freakboy3742 freakboy3742 left a comment

Choose a reason for hiding this comment

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

We're definitely getting closer. Most of the implementation now looks good; I've pushed a couple of cosmetic tweaks to the actual message text, but the basic flow and implementation now makes sense.

The one part that needs to be cleaned up now is an artefact of the refactor, plus the testing that flows on from that.

In the old code, the interface to bootstraps was create_bootstrap(), which handled both selection and instantiation of the bootstrap. This PR has split that up - which makes sense... but the API for create_boostrap()... which is then never called - and the testing is still focussed around calling create_bootstrap().

If a method isn't being used, we don't need to retain it :-)

On top of that, _instantiate_bootstrap() is 2 line implementation of fairly obvious logic that isn't re-used anywhere. I think it's safe to put that content directly into the single place it's used.

This means that the content that is currently in test_create_bootstrap() should really be in a test_select_bootstrap() method - this would be consistent with the fact that most of the test cases in test_create_bootstreap() were really tests of the selection process, not the instantiation process.
I'd suggest that instead of introducing a new _instantiate_boostrap() method, we repurpose the existing create_bootstrap() name to fill that purpose - that is rename _instantiate_bootstrap() to create_bootstrap().

This means a change to tests as well. test_creat_splitting test_create_bootstrap()into two parts - one testingtest_select_bootstrap() to test the selection process, and test_create_bootstrap() - since that capability was previously being tested

I've pushed an update doing the API simplification; however, this means the tests will now fail. If you update the tests to match what I've described here, we should be good to go

@moondial-pal
Copy link
Copy Markdown
Contributor Author

The continued guidance is much appreciated. I'll get to work on the changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add option to aid discoverability of third-party Briefcase bootstraps

3 participants