-
-
Notifications
You must be signed in to change notification settings - Fork 157
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
Add get_power_state()
#2257
Add get_power_state()
#2257
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.
Why not have these as properties? I know that you get these all these values via SDL_GetPowerInfo()
, but I have a feeling that it would make sense to have these as individual properties in the pygame API.
Reading this over, my main concern is that there are magic values ( I see two other possibilities:
What do you think? Another thing: |
Just realized this should have a basic test in the test suite. |
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.
The implementation looks good, good work.
I'd still like a little further discussion about the API. Maybe @ankith26 or @zoldalma999 has a take?
Yes I do have a take on a few alternative API ideas, one of which I mentioned in #1570 However, I'm not strongly against this PR, I would also be happy if we went with this, but just added an extra field to the dict that is the "raw SDL data as an enum" (so in my above example, I would like to instead do |
Since I was asked about this I think using None as absent value for integer values (battery_seconds and battery_percent) is a bit weird. Wouldn't -1 be better? Or maybe don't even set unknown values? And then we can return an empty dict instead of None as well. I do agree with Ankith, exposing the sdl constant as an extra field could be helpful to some people. However if we want to go with the enum way, maybe a general api for adding and handling enums would be nice (assuming we want to continue doing this in other places as well?). Or do we just hack it in through a python file or something like that? However, that is out of the scope of this pr. So I am up to just merge this without the const, and do it in a later pr |
|
@ankith26 Adding an enumerate class may be too complicated for this PR. Is it OK to add some constants instead? Like this:
Or maybe open another PR to handle the enum things (? |
One potential problem with adding the powerstate as a enum/flag/constant like this is that it undermines the whole "return None if state is unknown thing" Either the SDL state should be decomposed into its data components, or just the SDL state should be reported? It's a shame to get this far through implementation and still not have a decided API. Ankith wants the SDL state, I want the separated data, yet neither of us are so dead set in our approach. I just want to decide the API. I think it's either the current API or it returns a dictionary of {state, battery_percent, time} (AKA a direct port of SDL_GetPowerInfo) |
It sounds like everyone would be nearly happy if we added a 'state' enum corresponding to the Looks like adding an enum C side is a little complicated but I did find a useful Stackoverflow answer on the topic here: So you'd have a user API something like: power_info = pygame.system.get_power_state()
if power_info["state"] == pygame.system.PowerState.CHARGED:
# display green light It might be nice if the returned power_info was in the style of a dataclass instead of a dictionary, and if we are having a power_info = pygame.system.get_power_info()
if power_info.state == pygame.system.PowerState.CHARGED:
# display green light
elif power_info.charging:
print("Amount charged:", power_info.battery_percent) Though now that I've typed that I kind of hate it as it feels like we would have two different APIs to get battery status of "charging" versus "charged". Instead of a state enum, why don't we just add two other boolean fields Anyway then you'd end up with: power_state = pygame.system.get_power_state()
if power_state.on_battery:
#activate power saving mode
if power_state.charged:
# display green light
elif power_state.charging:
# display charging info
print("Amount charged:", power_info.battery_percent) I assume you can create a dataclass-like instance of a class via normal class creating even if it doesn't have all the same features, as it won't really matter for the end user. It'll just reduce the typing of the dictionary-esque padding e.g. https://stackoverflow.com/questions/4163018/create-an-object-using-pythons-c-api |
Strings in an interface are prone to typos (should be found by testing thought). The other thing I recommend is to wrap what you don't own, e.g. don't pass the SDL enum directly, wrap it instead. The DataClass example encapsulates the data better and could make clear, that those values are read only (only setter properties?). |
class _PowerState:
battery_seconds: int | None
battery_percent: int | None
# Attributes from SDL flags
on_battery: bool # Not plugged in, running on the battery
no_battery: bool # Plugged in, no battery available
charging: bool # Plugged in, charging battery
charged: bool # Plugged in, battery charged
# Additional attributes for convenience
plugged_in = not on_battery
has_battery = on_battery or not no_battery
def get_power_state() -> _PowerState | None:
... Does this satisfy all the requirements? |
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.
LGTM! I just have one minor nitpick that can be ignored if it's a bad suggestion
2f24228
to
1c7b7ab
Compare
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 great, thanks @yunline!
I'd like you to squash the commits down a bit before merging. Once you do that, go ahead and merge. :)
update docs Retuen None if the power state is unknown. fix memory leak add test for `get_power_state` python3.7 compat
return `_PowerState` instead of a dict Update tests for `get_power_state()` update docs for get_power_state compatible with py≤3.9 Fix pypy compat Remove empty doc string
Update docs compat for py < 3.10 _PowerState -> PowerState
- data_classes.py -> _data_classes.py - set the __module__ of PowerState to "pygame.system" - update stubs and tests
1c7b7ab
to
929400e
Compare
Fixes: #1570
Test Code: