Mic92 / python-mpd2

Python library which provides a client interface for the Music Player Daemon.
GNU Lesser General Public License v3.0
353 stars 119 forks source link

commands() returns commands which are not available #101

Open Pu-Anlai opened 6 years ago

Pu-Anlai commented 6 years ago

The documentation for commands() states that it returns "commands the current user has access to." However, after initiating an MPDClient object, I get several commands which have not been bound yet or do not exist at all.

from mpd import MPDClient
mpc = MPDClient()
mpc.connect('127.0.0.1', port=6600)

for c in filter(lambda x: x not in dir(mpc), mpc.commands()):
    print(c)

This outputs:

sticker
unmount
volume
Mic92 commented 6 years ago

Can you do connect with netcat and then type commands?

$ nc -v localhost 6600
OK MPD 0.20.0
commands
command: add
command: addid
command: addtagid
command: channels
command: clear
command: clearerror
command: cleartagid
command: close
command: commands
command: config
command: consume
command: count
...
Mic92 commented 6 years ago

What is the output of:

print(dir(mpc))

It my version it look as expected.

Pu-Anlai commented 6 years ago

Using netcat, the server returns those three commands as well (sticker, unmount, volume). But they don't appear when using dir.

>>> print(dir(mpc))
['NOOP', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__'
, '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__mod
ule__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '_
_str__', '__subclasshook__', '__weakref__', '_command_list', '_connect_tcp', '_connect_unix', '_execute
', '_fetch', '_hello', '_iterating', '_iterator_wrapper', '_parse_changes', '_parse_database', '_parse_
idle', '_parse_item', '_parse_list', '_parse_messages', '_parse_mounts', '_parse_neighbors', '_parse_no
thing', '_parse_object', '_parse_objects', '_parse_objects_direct', '_parse_outputs', '_parse_pair', '_
parse_pairs', '_parse_playlist', '_parse_playlists', '_parse_plugins', '_parse_raw_stickers', '_parse_s
ongs', '_parse_sticker', '_parse_stickers', '_pending', '_read_command_list', '_read_line', '_read_line
s', '_reset', '_rfile', '_send', '_sock', '_timeout', '_wfile', '_wrap_iterator', '_wrap_iterator_parse
rs', '_write_command', '_write_line', 'add', 'add_command', 'addid', 'addtagid', 'channels', 'clear', '
clearerror', 'cleartagid', 'close', 'command_list_end', 'command_list_ok_begin', 'commands', 'config', 
'connect', 'consume', 'count', 'crossfade', 'currentsong', 'decoders', 'delete', 'deleteid', 'disableou
tput', 'disconnect', 'enableoutput', 'fetch_add', 'fetch_addid', 'fetch_addtagid', 'fetch_channels', 'f
etch_clear', 'fetch_clearerror', 'fetch_cleartagid', 'fetch_close', 'fetch_commands', 'fetch_config', '
fetch_consume', 'fetch_count', 'fetch_crossfade', 'fetch_currentsong', 'fetch_decoders', 'fetch_delete'
, 'fetch_deleteid', 'fetch_disableoutput', 'fetch_enableoutput', 'fetch_find', 'fetch_findadd', 'fetch_
idle', 'fetch_kill', 'fetch_list', 'fetch_listall', 'fetch_listallinfo', 'fetch_listfiles', 'fetch_list
mounts', 'fetch_listneighbors', 'fetch_listplaylist', 'fetch_listplaylistinfo', 'fetch_listplaylists', 
'fetch_load', 'fetch_lsinfo', 'fetch_mixrampdb', 'fetch_mixrampdelay', 'fetch_mount', 'fetch_move', 'fe
tch_moveid', 'fetch_next', 'fetch_notcommands', 'fetch_outputs', 'fetch_outputvolume', 'fetch_password'
, 'fetch_pause', 'fetch_ping', 'fetch_play', 'fetch_playid', 'fetch_playlist', 'fetch_playlistadd', 'fe
tch_playlistclear', 'fetch_playlistdelete', 'fetch_playlistfind', 'fetch_playlistid', 'fetch_playlistin
fo', 'fetch_playlistmove', 'fetch_playlistsearch', 'fetch_plchanges', 'fetch_plchangesposid', 'fetch_pr
evious', 'fetch_prio', 'fetch_prioid', 'fetch_random', 'fetch_rangeid', 'fetch_readcomments', 'fetch_re
admessages', 'fetch_rename', 'fetch_repeat', 'fetch_replay_gain_mode', 'fetch_replay_gain_status', 'fet
ch_rescan', 'fetch_rm', 'fetch_save', 'fetch_search', 'fetch_searchadd', 'fetch_searchaddpl', 'fetch_se
ek', 'fetch_seekcur', 'fetch_seekid', 'fetch_sendmessage', 'fetch_setvol', 'fetch_shuffle', 'fetch_sing
le', 'fetch_stats', 'fetch_status', 'fetch_sticker_delete', 'fetch_sticker_find', 'fetch_sticker_get', 
'fetch_sticker_list', 'fetch_sticker_set', 'fetch_stop', 'fetch_subscribe', 'fetch_swap', 'fetch_swapid
', 'fetch_tagtypes', 'fetch_toggleoutput', 'fetch_umount', 'fetch_unsubscribe', 'fetch_update', 'fetch_
urlhandlers', 'fileno', 'find', 'findadd', 'idle', 'idletimeout', 'iterate', 'kill', 'list', 'listall',
 'listallinfo', 'listfiles', 'listmounts', 'listneighbors', 'listplaylist', 'listplaylistinfo', 'listpl
aylists', 'load', 'lsinfo', 'mixrampdb', 'mixrampdelay', 'mount', 'move', 'moveid', 'mpd_version', 'nex
t', 'noidle', 'notcommands', 'outputs', 'outputvolume', 'password', 'pause', 'ping', 'play', 'playid', 
'playlist', 'playlistadd', 'playlistclear', 'playlistdelete', 'playlistfind', 'playlistid', 'playlistin
fo', 'playlistmove', 'playlistsearch', 'plchanges', 'plchangesposid', 'previous', 'prio', 'prioid', 'ra
ndom', 'rangeid', 'readcomments', 'readmessages', 'remove_command', 'rename', 'repeat', 'replay_gain_mo
de', 'replay_gain_status', 'rescan', 'rm', 'save', 'search', 'searchadd', 'searchaddpl', 'seek', 'seekc
ur', 'seekid', 'send_add', 'send_addid', 'send_addtagid', 'send_channels', 'send_clear', 'send_clearerr
or', 'send_cleartagid', 'send_close', 'send_commands', 'send_config', 'send_consume', 'send_count', 'se
nd_crossfade', 'send_currentsong', 'send_decoders', 'send_delete', 'send_deleteid', 'send_disableoutput
', 'send_enableoutput', 'send_find', 'send_findadd', 'send_idle', 'send_kill', 'send_list', 'send_lista
ll', 'send_listallinfo', 'send_listfiles', 'send_listmounts', 'send_listneighbors', 'send_listplaylist'
, 'send_listplaylistinfo', 'send_listplaylists', 'send_load', 'send_lsinfo', 'send_mixrampdb', 'send_mi
xrampdelay', 'send_mount', 'send_move', 'send_moveid', 'send_next', 'send_notcommands', 'send_outputs',
 'send_outputvolume', 'send_password', 'send_pause', 'send_ping', 'send_play', 'send_playid', 'send_pla
ylist', 'send_playlistadd', 'send_playlistclear', 'send_playlistdelete', 'send_playlistfind', 'send_pla
ylistid', 'send_playlistinfo', 'send_playlistmove', 'send_playlistsearch', 'send_plchanges', 'send_plch
angesposid', 'send_previous', 'send_prio', 'send_prioid', 'send_random', 'send_rangeid', 'send_readcomm
ents', 'send_readmessages', 'send_rename', 'send_repeat', 'send_replay_gain_mode', 'send_replay_gain_st
atus', 'send_rescan', 'send_rm', 'send_save', 'send_search', 'send_searchadd', 'send_searchaddpl', 'sen
d_seek', 'send_seekcur', 'send_seekid', 'send_sendmessage', 'send_setvol', 'send_shuffle', 'send_single
', 'send_stats', 'send_status', 'send_sticker_delete', 'send_sticker_find', 'send_sticker_get', 'send_s
ticker_list', 'send_sticker_set', 'send_stop', 'send_subscribe', 'send_swap', 'send_swapid', 'send_tagt
ypes', 'send_toggleoutput', 'send_umount', 'send_unsubscribe', 'send_update', 'send_urlhandlers', 'send
message', 'setvol', 'shuffle', 'single', 'stats', 'status', 'sticker_delete', 'sticker_find', 'sticker_
get', 'sticker_list', 'sticker_set', 'stop', 'subscribe', 'swap', 'swapid', 'tagtypes', 'timeout', 'tog
gleoutput', 'umount', 'unsubscribe', 'update', 'urlhandlers', 'use_unicode']

Thanks for the lightning fast reply btw.

Mic92 commented 6 years ago

The following code shows the correct result:

from mpd import MPDClient
mpc = MPDClient()
mpc.connect('127.0.0.1', port=6600)

print(set(mpc.commands()) & set(dir(mpc)))
Pu-Anlai commented 6 years ago

Yes, that shows me what commands are available. But shouldn't mpc.commands() do that as well?

Mic92 commented 6 years ago

Your code was not correct. Using set is also faster (also this probably does not matter here).

Pu-Anlai commented 6 years ago

I don't understand. Isn't commands() supposed to list all available commands? Because right now, it lists some that are not available.

>>> from mpd import MPDClient
>>> mpc = MPDClient()
>>> mpc.connect('127.0.0.1', port=6600)
>>> mpc.commands()
['add', 'addid', 'addtagid', 'albumart', 'channels', 'clear', 'clearerror', 'cleartagid', 'close', 'com
mands', 'config', 'consume', 'count', 'crossfade', 'currentsong', 'decoders', 'delete', 'deleteid', 'di
sableoutput', 'enableoutput', 'find', 'findadd', 'idle', 'kill', 'list', 'listall', 'listallinfo', 'lis
tfiles', 'listmounts', 'listpartitions', 'listplaylist', 'listplaylistinfo', 'listplaylists', 'load', '
lsinfo', 'mixrampdb', 'mixrampdelay', 'mount', 'move', 'moveid', 'newpartition', 'next', 'notcommands',
 'outputs', 'outputset', 'partition', 'password', 'pause', 'ping', 'play', 'playid', 'playlist', 'playl
istadd', 'playlistclear', 'playlistdelete', 'playlistfind', 'playlistid', 'playlistinfo', 'playlistmove
', 'playlistsearch', 'plchanges', 'plchangesposid', 'previous', 'prio', 'prioid', 'random', 'rangeid', 
'readcomments', 'readmessages', 'rename', 'repeat', 'replay_gain_mode', 'replay_gain_status', 'rescan',
 'rm', 'save', 'search', 'searchadd', 'searchaddpl', 'seek', 'seekcur', 'seekid', 'sendmessage', 'setvo
l', 'shuffle', 'single', 'stats', 'status', 'sticker', 'stop', 'subscribe', 'swap', 'swapid', 'tagtypes
', 'toggleoutput', 'unmount', 'unsubscribe', 'update', 'urlhandlers', 'volume']

As you can see, this list includes among others sticker, unmount and volume. Yet:

>>> mpc.sticker
Traceback (most recent call last):
  File "<input>", line 1, in <module>
    mpc.sticker
AttributeError: 'MPDClient' object has no attribute 'sticker'
>>> mpc.unmount
Traceback (most recent call last):
  File "<input>", line 1, in <module>
    mpc.unmount
AttributeError: 'MPDClient' object has no attribute 'unmount'
>>> mpc.volume
Traceback (most recent call last):
  File "<input>", line 1, in <module>
    mpc.volume
AttributeError: 'MPDClient' object has no attribute 'volume'
Mic92 commented 6 years ago

In python-mpd2 there is sticker_get(), sticker_delete() and sticker_set() instead of a sticker function. The function unmount is spelled in incorrectly in the library: https://github.com/Mic92/python-mpd2/blob/d9860f42246d903023106274b8a427fc9849e962/mpd/base.py#L309

volume was deprecated at some point by mpd and removed from this library: https://github.com/Mic92/python-mpd2/blob/master/doc/changes.rst#changes-in-041

Pu-Anlai commented 6 years ago

Aaaah, I see. So basically commands() just lists the commands that the server makes available to clients, not necessarily commands that are available through python-mpd2.