-
-
Notifications
You must be signed in to change notification settings - Fork 695
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
Replace reapply() with bare apply() #3160
Conversation
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 with #3159, a fine implementation of a feature... if we want to pursue that feature.
To my mind. apply()
and reapply()
as names aren't causing major issues at present. Maybe they could be a little clearer, but they're fairly deep internals that most users won't need to see, and they're not fundmentally wrong... and naming is hard 😄. In the places the methods are seen in Toga APIs, the existing naming makes at least some sense - Android needs to reapply all styles after a widget is constructed, for example.
If anything, it's problematic that they're visible methods at all - we've had plenty of examples of users in the past who are trying to get (for example) background colors to work on a widget that doesn't support them, and exclaim "I've even called reapply(), and it didn't work!!".
If we're going to go to the trouble of a rename, I'd rather a name that moves them out of the public namespace to remove any illusion that they should be user-callable methods.
Also - this is another one where I'd be interested to hear @mhsmith's thoughts. |
I hadn't thought of that, but it's not a bad idea. I guess it depends on where one draws the API line. These methods could be said to be part of Travertino's "public" API, and consumed by Toga... but since they're not designed to ultimately be interacted with by non-library code at all, it isn't ideal that they end up visible on Pack. |
Wait - scratch that. I'm getting myself tied in knots between |
Naming things certainly is hard... Am I correct in guessing that in proposals like this, where the implementation is simple but the goal isn't certain, it would probably be smarter to open an issue first? I was erring on the "Show up with code attached to your idea" side, but I'm realizing now that probably doesn't apply as much when the code is mostly just renaming. |
Generally speaking, yes. The only notable exceptions would be (a) when the subject has already been discussed as a side effect of some other change, or (b) when there's some question about technical feasibility (e.g., a complicated set of changes needed for compatibility reasons, where having a proof of concept is likely more helpful than a description of proposed changes). |
I agree the rename makes sense, as the current name is a bit misleading. But adding underscores to all the non-public methods probably isn't worth the churn, especially since we have no indication that people are using them. As I said in #3159, this method has never been in any documentation or example code, so I don't think it requires a deprecation cycle or a public change note. |
There's a difference though: unlike |
Good point – I guess even after locking the Toga and Travertino versions to each other, we still need to keep Travertino compatible with old Toga versions until a reasonable time has passed since the 0.5.0 release. |
Throwing this out there on the basis of "there's no such thing as a bad idea"... Another possibility would be to modify |
This was the first thing I thought of, and in a vacuum, I'd prefer the API usage. It's definitely strange how it would interact with Pack defining its apply method.... Although, here's a thought. What if base apply applies all with no arguments, and raises NotImplemented if given one. Pack's job, then, is to just call super().apply() if it doesn't have arguments, and otherwise do its thing. |
Yeah, but that gets into all sorts of weird circular calls where a subclass is calling the superclass to call the subclass... and any historical usage will straight up break, with a warning raised by If we accept that every end-user writing an We actually avoid a bunch of function calls in the apply all case since we won't need to call |
I suppose there'd be nothing stopping us, even, from letting |
82e7b8a
to
d3babc0
Compare
(I didn't actually change anything just now, only based it onto main.) |
True - the boilerplate for an end-user's apply method essentially becomes:
There's even some optimization opportunities, because you can make one call to |
Yeah, it'll be good to not set the font four times on every single |
Would it be better to rename this PR, commit a revert, and start over based on what we've discussed, or close this one and open a new one? |
The whole thing will be turned into a single merge commit when it's accepted, so unless it's especially onerous, I'd be inclined to keep the discussion all in one place and update this PR. |
More convenient for both the caller and callee would be:
However, to avoid redundant applications of font, we might also need to combine |
👍
That's an interesting one. Currently, calling any property's setter will apply it after setting the value. We'll need some way to avoid doing that on each assignment in |
Interesting. I'm not sure how declaration lines 147 and 260 aren't being called all of a sudden, when they're there to handle being assigned no value in the dataclass constructor... I think I'm beginning to feel you on the "troubleshooting doing anything novel with dataclasses" front, @freakboy3742. I know the primary motivation for changing the style property syntax in beeware/travertino#141 was to get code completion of property names in IDEs when creating Pack instances... However, now that style properties will probably be declared directly on widgets most of the time, I'm starting to wonder if it's worth the complexity of using a dataclass just for that, considering the descriptors all work perfectly well without it. |
Another thought: even if we were to abandon the use of dataclass for the time being, we could always revisit it once we drop support for Python 3.9. Consistent availability of the |
That's starting to sound like an overlap with #2938...
I'd be looking at the changes to the
Honestly, I'd be more inclined to accelerate the deprecation of 3.9. It's only got 8 months left regardless; if it's causing problems, I could almost get on board with 0.5 being 3.10+ only. |
Conceptually, at least. But I'm not sure they're actually intertwined. Layout calculations can beget further layout calculations, and they also have to happen all over again when things are resized. Styles, on the other hand, should stay the same until explicitly changed, so they shouldn't need to worry about being run asynchronously or deferred to once-per-loop. This should be much simpler (I say now)...
I think you're right; when I have time to really sit down with it, that's where I'll look first.
I wouldn't say I know that it's causing problems, but... I guess that is itself the problem. It adds complexity to the implementation and testing, and it's one more layer to have to look through when troubleshooting. I believe this is the only place I personally have tripped over 3.9 support, but I see that removing it would also simplify use of TypeAlias and entry points. |
Turns out it was the ordering of applying I've also split the mock for |
|
...Well shit, I somehow missed that in the docs. |
So I guess that's less necessary than I thought. I can change it back if it seems frivolous, though I think it still makes some of the tests' intent clearer. |
Regarding the possibility of a "lock" to prevent redundant Font creation — while I think it seems relatively straightforward, I think I'd still rather tackle it in a discrete PR. |
Oh - I agree it's 100% a gap in the API for mock. There should be an It would make for a nice little CPython contribution project... but then we wouldn't be able to use the feature for 5 years, so the motivation to add it isn't high.
I don't think it's frivolous at all - verifying that we're not applying a property multiple times (or similar) is an important part of what we're verifying here. |
Well, what I meant is that we can verify that by using one mock and then comparing directly against its |
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.
Well, what I meant is that we can verify that by using one mock and then comparing directly against its
call_list
. Splitting it up is just a more convenient and legible wrapper.
Ah - I hadn't looked at the code yet to see what you've done.
I think I can understand where you're coming from, but I think that approach potentially misses some cases. Consider a case where due to some error, both apply()
and apply("foo"); apply("bar")
are invoked. We're only expecting the individual calls to apply foo and bar; so we assert the call list on _apply_names
... and miss that _apply_all
has been invoked. Essentially every time we assert apply_names()
, we need to assert that _apply_all()
hasn't been invoked, and vice versa.
Otherwise, the PR is looking fairly good; a couple of minor comments inline.
True. It's the same situation we were/are in, before applying this PR, with |
Co-authored-by: Russell Keith-Magee <russell@keith-magee.com>
Co-authored-by: Russell Keith-Magee <russell@keith-magee.com>
This reverts commit f1ca69c.
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.
Looks good, except for a couple of errors of usage in some mock_call
assertions, and a need for some clarity on one kind of those assertions.
Co-authored-by: Russell Keith-Magee <russell@keith-magee.com>
Co-authored-by: Russell Keith-Magee <russell@keith-magee.com>
Co-authored-by: Russell Keith-Magee <russell@keith-magee.com>
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.
This is a nice set of cleanups - thanks!
The name of
BaseStyle.reapply()
doesn't really reflect what it does. The presence ofapply()
andreapply()
implies they do at least roughly the same thing, except one is for the first time and the other is for subsequent uses — whereas the actual difference is thatapply()
applies a single property, whilereapply()
applies all of them. Ironically, it's the first of the two methods to be (successfully) called, once the applicator is assigned.I'd like to renamereapply
toapply_all
. I'm also all ears to alternate spellings, if you think something else would be preferable.EDIT: Based on discussion, this now modifies
apply()
such that calling it with no arguments replaces the use ofreapply()
.PR Checklist: