Skip to content
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

fuo协议Show命令增强-Add Features #380

Merged
merged 9 commits into from
Jul 2, 2020
5 changes: 5 additions & 0 deletions fuocore/cmds/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import logging

from fuocore.excs import FuoException
from fuocore.router import ShowCmdException

from .base import cmd_handler_mapping

from .help import HelpHandler # noqa
Expand Down Expand Up @@ -66,6 +68,9 @@ def exec_cmd(cmd, *args, app):
playlist=playlist,
live_lyric=live_lyric)
rv = handler.handle(cmd)
except ShowCmdException:
logger.exception('handle cmd({}) error'.format(cmd))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

像这种已经被正确处理了的错误,打个 warning/error 级别就可以了。

打 exception 的话,一般是意料之外的错误。比如未知的错误等。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

谢谢,学习到了

return False, 'show command not correct'
except Exception:
logger.exception('handle cmd({}) error'.format(cmd))
return False, 'internal server error'
Expand Down
141 changes: 119 additions & 22 deletions fuocore/cmds/show.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,11 @@
import logging
from urllib.parse import urlparse

from fuocore.router import Router
from fuocore.utils import reader_to_list, to_reader
from fuocore.router import Router

from .base import AbstractHandler


logger = logging.getLogger(__name__)


Expand All @@ -39,54 +38,152 @@ def handle(self, cmd):
return rv


def noexception_handler_default(obj_name, obj_identifier, obj):
if obj is None:
return "{} identified by {} is not found"\
.format(obj_name, obj_identifier)
return obj


def noexception_handler_lyric(obj_name, obj_identifier, obj):
song, sid = obj, obj_identifier
if song is None:
return "{} identified by {} is not found"\
.format(obj_name, sid)

if song.lyric is None:
return "no lyric for this song, enjoy it ~"

return song.lyric.content


def noexception_handler_user(obj_name, obj_identifier, obj):
user, uid = obj, obj_identifier
if user is not None:
return user
elif uid == 'me':
return "User is not logged in in current session(plugin)"
else:
return "No {} with uid {} ".format(obj_name, uid)


def noexception_handler_readerlist(obj_name, obj_identifier, obj):
if obj is None:
return "No {} found by {} "\
.format(obj_name, obj_identifier)

# quick and dirty implement
if obj_name == 'playlists':
return reader_to_list(to_reader(obj, "songs"))
else:
return reader_to_list(to_reader(obj, "albums"))


def get_from_provider(
req,
provider,
obj_identifier,
obj_name,
handler=noexception_handler_default):
provider_path_name = provider
provider = req.ctx['library'].get(provider)

if provider is None:
return "No such provider : {}".format(provider_path_name)

try:
if obj_name == 'songs':
obj = provider.Song.get(obj_identifier)
elif obj_name == 'artists':
obj = provider.Artist.get(obj_identifier)
elif obj_name == 'ablums':
obj = provider.Album.get(obj_identifier)
elif obj_name == 'playlists':
obj = provider.Playlist.get(obj_identifier)
elif obj_name == 'users':
if obj_identifier == 'me':
obj = provider._user
else:
obj = provider.User.get(obj_identifier)
else:
obj = None
except Exception:
return "resource-{} identified by {} is unavailable in {}"\
.format(obj_name, obj_identifier, provider.name)
else:
return handler(obj_name, obj_identifier, obj)


@route('/')
def list_providers(req):
return req.ctx['library'].list()


@route('/<provider>/songs/<sid>')
def song_detail(req, provider, sid):
provider = req.ctx['library'].get(provider)
song = provider.Song.get(sid)
return song
return get_from_provider(req, provider, sid, "songs")


@route('/<provider>/songs/<sid>/lyric')
def lyric(req, provider, sid):
provider = req.ctx['library'].get(provider)
song = provider.Song.get(sid)
if song.lyric:
return song.lyric.content
return ''
return get_from_provider(req, provider, sid, "songs", noexception_handler_lyric)


@route('/<provider>/artists/<aid>')
def artist_detail(req, provider, aid):
provider = req.ctx['library'].get(provider)
return provider.Artist.get(aid)
return get_from_provider(req, provider, aid, "artists")


@route('/<provider>/albums/<bid>')
def album_detail(req, provider, bid):
provider = req.ctx['library'].get(provider)
return provider.Album.get(bid)
return get_from_provider(req, provider, bid, "albums")


'''
------------------------------------
Original Route -- get User by uid
example : fuo show fuo://<provider>/users/12345678
------------------------------------
Issue #317
Description: fuo show nehancement -- show info about current user
example : fuo show fuo://<provider>/users/me
'''


@route('/<provider>/users/<uid>')
def user_detail(req, provider, uid):
provider = req.ctx['library'].get(provider)
return provider.User.get(uid)
return get_from_provider(req, provider, uid, "users", noexception_handler_user)


@route('/<provider>/playlists/<pid>')
def playlist_detail(req, provider, pid):
provider = req.ctx['library'].get(provider)
return provider.Playlist.get(pid)
return get_from_provider(req, provider, pid, "playlists")


@route('/<provider>/playlists/<pid>/songs')
def playlist_songs(req, provider, pid):
provider = req.ctx['library'].get(provider)
playlist = provider.Playlist.get(pid)
songs = reader_to_list(to_reader(playlist, "songs"))
return songs
return get_from_provider(
req,
provider,
pid,
"playlists",
noexception_handler_readerlist
)


'''
Issue #317
Description: fuo show enhancement -- show all albums of an artist identified by aid
example : fuo show fuo://<provider>/artists/<aid>/albums
'''


@route('/<provider>/artists/<aid>/albums')
def albums_of_artist(req, provider, aid):
return get_from_provider(
req,
provider,
aid,
"artists",
noexception_handler_readerlist
)
25 changes: 22 additions & 3 deletions fuocore/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,22 @@
from urllib.parse import parse_qsl, urlsplit


class NotFound(Exception):
class ShowCmdException(Exception):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pass


# Rule not found
class NotFound(ShowCmdException):
def __init__(self, rule):
self.rule = rule

def __str__(self):
# use backstrace lib (the format_exc/print_exc) causes fail
# maybe the coroutine issue ?
uri_msg = "Bad Uri Exception: fuo://{}".format(self.rule)
return uri_msg
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

我觉得可以直接在抛错的时候把文字内容加进去,比如

raise NotFound(f"Bad Uri Exception: fuo://{self.rule}")



def match(url, rules):
"""找到 path 对应的 rule,并解析其中的参数

Expand All @@ -30,7 +42,8 @@ def match(url, rules):
query = dict(parse_qsl(qs))
params = match.groupdict()
return rule, params, query
raise NotFound

raise NotFound(path)


def _validate_rule(rule):
Expand Down Expand Up @@ -96,7 +109,13 @@ def wrapper(*args, **kwargs):
return decorator

def dispatch(self, uri, ctx):
rule, params, query = match(uri, self.rules)
try:
rule, params, query = match(uri, self.rules)
except NotFound:
# pass it to the exception handle procedure in __init__.py
raise
return None
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里只是 re-raise 了一下,看起来 try ... except... 不是很有必要?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

对,代码删改到后面,变成这一段只是为了使得__init__.py能捕获得异常的信息,所以就简单的re-raise,应该有更好的方法来着


handler = self.handlers[rule]
req = Request(uri=uri, rule=rule, params=params, query=query, ctx=ctx)
return handler(req, **params)