-
-
Notifications
You must be signed in to change notification settings - Fork 671
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
[widget Audit] toga.App #2075
[widget Audit] toga.App #2075
Conversation
52b403c
to
fec495d
Compare
3ca628a
to
6a7a7fd
Compare
6a7a7fd
to
cceeb5f
Compare
The missing coverage on toga_winforms\app.py line 83 should be fixed once beeware/briefcase-windows-VisualStudio-template#23 has been merged, and propagated to the stub EXEs in the |
With the last commit, macOS is crashing consistently in CI after the third test. I can't reproduce the problem locally, and the changes since the last time it passed don't contain anything that could affect macOS, other than a change to a test which it never got remotely close to running. |
def __isub__(self, other: Window) -> None: | ||
self.discard(other) | ||
return self | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Although they're no longer required, there will be enough code in existence that uses these methods that I don't think we can delete them completely. Toga's own examples contain a bunch of uses of this.
At the very least, they should exist, but be no-ops that log DeprecationWarnings.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, I've restored them and added warnings, since they were never consistent with the standard set interface anyway.
I could only find one remaining usage in the examples, which I see you've already removed in #2160.
raise ValueError( | ||
"The `windows` constructor argument of toga.App has been removed. " | ||
"Windows are now automatically added to the current app." | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why a full exception? Elsewhere we've logged a DeprecationWarning and transformed the input as best we can.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As part of the Window audit, I changed it so that Windows are added to the App when they're created, instead of when they're shown. Then as part of this PR, I added a check to make sure that the App is created before the Window:
Lines 134 to 137 in ff64a99
self._app = None | |
if App.app is None: | |
raise RuntimeError("Cannot create a Window before creating an App") | |
App.app.windows.add(self) |
I appreciate that this may break some existing code, but I think it's worth it because it makes it significantly easier to reason about the relationship between App and Window, both for us and for the users. Anyone who's been following the style of the Toga examples will not be affected.
This means that any windows passed to the App constructor must already have been added to a different App. so there's no way we can handle that situation sensibly.
core/src/toga/app.py
Outdated
"""The name of the distribution used to load metadata with | ||
:any:`importlib.metadata` (read-only).""" | ||
return self._app_name | ||
return self._distribution_name |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On reflection: I'm not 100% sure this deprecation/rename is warranted.
The name
->formal_name
is definitely called for; name
is ambiguous, especially given the usage in PEP621 context.
However, I don't think renaming app_name
->distribution_name
is as much of a win.
- PEP621 talks about "distribution names" as a noun, but doesn't actually use
distribution_name
anywhere. There are APIs tocanonicalize_name()
andnormalize_name()
, which reference theName
metadata field. - Most of PEP621 is focussed on distributing libraries to PyPI, not "apps" in the Briefcase sense.
- The docs for
Name
call it the "distribution name"; I think you could reasonably argue that the "distribution" in any Toga/Briefcase context is an "app" - Briefcase uses
app_name
extensively, so we'd be facing an inconsistency that we'd need to resolve. app_name
isn't ambiguous, and is easy enough to document as "the distribution name".- It's code churn for existing uses, and the new name is longer.
In short, it's a disruptive name change that has ongoing consequences on Briefcase, but isn't actually converging on a specific usage that the broader Python ecosystem uses.
Replacing app_name
with name
at some point in the future would make some sense, as that would be converging on PEP621 usage/naming - but I don't think the interim name change actually helps that much.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, that makes sense; I'll revert the rename.
Things will be less confusing once we remove the deprecated name
property, so I'll make an issue to remind us to do that (#2212).
@@ -135,7 +136,7 @@ def action4(widget): | |||
|
|||
# The order in which commands are added to the app or the toolbar won't | |||
# alter anything. Ordering is defined by the command definitions. | |||
self.app.commands.add(cmd1, cmd0, cmd6, cmd4, cmd3) | |||
self.app.commands.add(cmd1, cmd0, cmd6, cmd4, cmd3, cmd7) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not adding cmd7 here was an explicit test of the "adding to toolbar implies adding to app" case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reverted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On second thoughts, I think it's worth keeping this to verify that adding a command to both places doesn't cause any problems. And I've added a similar case to the core tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As long as we've got an example of all three possibilities (app only, toolbar only, app and toolbar), 👍.
main_window.hide() | ||
assert app.current_window is None | ||
assert app.current_window in [None, main_window] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can definitely live with this for now, but it would be worth logging as a bug that should be possible to fix.
The last commit has caused failures on Windows and macOS. I'm currently looking into the Windows one, but I haven't started on macOS. |
core/src/toga/app.py
Outdated
def __iadd__(self, window: Window) -> None: | ||
# The standard set type does not have a += operator. | ||
warn("Instead of +=, use add()", DeprecationWarning, stacklevel=2) | ||
self.add(window) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since any user-space usage of += or -= is going to be fighting against Toga's internal window management, my inclination is to make these two no-ops - retain the API, but raise a warning that leads the user to you don't need to do this at all, rather than suggesting they need to use a different API name.
For future reference, the Windows failure was a memory leak detected by |
Audit of App, DocumentApp, Document and Command
Builds on #2058.
path
rather thanfilename
; and Documents are now expected to provide acreate()
method that assignsmain_window
as part of their creation process.App.exit()
now exits unconditionally, rather than triggering "can I close" logic. This matches the behavior ofWindow.close()
toga
base namespace. These classes shouldn't be needed by end users; they're internal details.Fixes:
Gtk.ToolButton
expects aGtk.Image
for the icon, not aGdkPixbuf.Pixbuf
#2152Audit checklist