-
Notifications
You must be signed in to change notification settings - Fork 46
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
Make class(es) more self-contained, reduce globals #146
base: master
Are you sure you want to change the base?
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.
3f4d8c4 - I'm not sure I understand this one; maybe it's just been too long since I looked at this code, but why is __wrapper
being made a class property? If it's assigned in __init__()
, then it should probably be an instance property (i.e. self._wrapper
).
Normally, yes, I'd agree. But that didn't work, because the callback functions aren't methods — they don't have access to |
(Forgot the ping: @grawity ) |
def __get_volume(): | ||
vol = float(mpd_wrapper.last_status().get('volume', 0)) | ||
vol = float(MPRISInterface.__wrapper.last_status().get('volume', 0)) | ||
if vol > 0: | ||
return vol / 100.0 | ||
else: | ||
return 0.0 | ||
|
||
def __set_volume(value): | ||
if value >= 0 and value <= 1: | ||
mpd_wrapper.setvol(int(value * 100)) | ||
MPRISInterface.__wrapper.setvol(int(value * 100)) | ||
return |
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.
@grawity This is what I was referring to — the setters and getters aren't defined as methods of MPRISInterface
, so they don't have access to self
.
# Player methods | ||
@dbus.service.method(__player_interface, in_signature='', out_signature='') | ||
def Next(self): | ||
mpd_wrapper.next() | ||
MPRISInterface.__wrapper.next() | ||
return |
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.
@grawity I could use self.__wrapper
for these methods, if you prefer. I decided to just be consistent, but I'm open to changing it if that was the wrong call.
@@ -247,7 +248,7 @@ class MPDWrapper(object): | |||
errors and similar | |||
""" | |||
|
|||
def __init__(self, params): | |||
def __init__(self, params, loop=None): |
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.
Shouldn't loop
be a required argument ?
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.
Wow, ancient history, I don't know how I missed these! Sorry about that.
...I think I originally set these up as defaulted arguments because I didn't want to change the class constructors' semantics until I had my additions finalized. But they probably don't need to stay in that state now.
As far as loop
goes, though... I mean, I'm not sure it really has to be required.
The only reason loop
is passed in is so the relaunch code in _name_owner_changed_callback()
can call self._loop.quit()
. If self._loop
is None
(it checks), it just won't call quit()
on it.
Which... seems like it would be fine? In situations where a loop
isn't supplied (say, in testing).
|
||
def __init__(self, params): | ||
def __init__(self, params, mpd_wrapper=None): |
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.
mpd_wrapper
is required too
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.
mpd_wrapper
, OTOH... yeah. I absolutely agree, it needs to be required. I'll fix that and rebase this PR to the current HEAD now.
Pushed 6b246e4 to see what it needs to make the wrapper an instance of the class. Feels a bit more idiomatic python to me Overall it's great to be able to run mpDris2 in the repl |
This PR contains a set of what I'm calling "quality of life" changes for the code. Nothing user-visible, this is all an attempt to make the
MPDWrapper
class and its helpers more self-contained, and importable/usable outside of thempDris2
source file itself — for testing/debugging purposes. The user should see absolutely no difference in normal operation.Specifically, this PR eliminates all references from inside the class code to symbols that are only defined if the
if __name__== '__main__'
block is run. As a result, it's now possible to import the class into an interactive session and call methods on it by hand, without it crashing due to things likempd_wrapper
andloop
being undefined, ornotification
not being callable because its value isNone
.Specific changes (as separate commits):
__main__
-only code)notification
in theMPDWrapper.__init__()
code asself._notification
, since it's never used in the__main__
code but all of the class code assumes it's been properly initializedloop
only in the__main__
code (I agree that's a good idea), but pass it in to theMPDWrapper()
constructor and useself._loop
to access it later.MPDWrapper
instance in toMPRISInterface()
along with theparams
, and store it asMPRISInterface.__wrapper
. Then, use that to make calls back to it, instead of trying to usempd_wrapper
which is undefined if the__main__
code wasn't executedWith these changes, it's possible to debug the code interactively via the REPL (after running
ln -s mpDris2 mpDris2.py
), all that's required is to set up theMainLoop
and create aparams
dictionary, then pass them both toMPDWrapper()
thusly:(...and it does.)