Cleaned up SubredditContent.from_name

This commit is contained in:
Michael Lazar
2016-07-20 00:45:45 -07:00
parent 3f90fdc70c
commit e7c2d82d93
4 changed files with 114 additions and 99 deletions

View File

@@ -48,6 +48,7 @@ The ``/`` prompt accepts subreddits in the following formats
* ``python`` * ``python``
* ``/r/python`` * ``/r/python``
* ``/r/python/new`` * ``/r/python/new``
* ``/r/python/controversial-year``
* ``/r/python+linux`` supports multireddits * ``/r/python+linux`` supports multireddits
* ``/r/front`` will redirect to the front page * ``/r/front`` will redirect to the front page
* ``/u/me`` will display your submissions * ``/u/me`` will display your submissions

View File

@@ -361,19 +361,10 @@ class SubredditContent(Content):
list for repeat access. list for repeat access.
""" """
def __init__( def __init__(self, name, submissions, loader, order=None):
self,
name,
submissions,
loader,
order=None,
listing='r',
period=None):
self.name = name self.name = name
self.order = order self.order = order
self.listing = listing
self.period = period
self._loader = loader self._loader = loader
self._submissions = submissions self._submissions = submissions
self._submission_data = [] self._submission_data = []
@@ -388,114 +379,136 @@ class SubredditContent(Content):
raise exceptions.SubredditError('No submissions') raise exceptions.SubredditError('No submissions')
@classmethod @classmethod
def from_name(cls, reddit, name, loader, order=None, query=None, def from_name(cls, reddit, name, loader, order=None, query=None):
listing='r', period=None): """
Params:
reddit (praw.Reddit): Instance of the reddit api.
name (text): The name of the desired subreddit, user, multireddit,
etc. In most cases this translates directly from the URL that
reddit itself uses. This is what users will type in the command
prompt when they navigate to a new location.
loader (terminal.loader): Handler for the load screen that will be
displayed when making http requests.
order (text): If specified, the order that posts will be sorted in.
For `top` and `controversial`, you can specify the time frame
by including a dash, e.g. "top-year". If an order is not
specified, it will be extracted from the name.
query (text): Content to search for on the given subreddit or
user's page.
"""
# Strip leading, trailing, and redundant backslashes # Strip leading, trailing, and redundant backslashes
name_list = [seg for seg in name.strip(' /').split('/') if seg] parts = [seg for seg in name.strip(' /').split('/') if seg]
name_order = None
if len(name_list) > 1 and name_list[0] in ['r', 'u', 'user', 'domain']: # Check for the resource type, assume /r/ as the default
listing, name_list = name_list[0], name_list[1:] if len(parts) > 3 and parts[2] == ['m']:
if len(name_list) == 2: # E.g. /u/multi-mod/m/android
name, name_order = name_list resource_root, parts = '/'.join(parts[:3]), parts[3:]
elif len(name_list) in [3, 4] and name_list[1] == 'm': if len(parts) > 1 and parts[0] in ['r', 'u', 'user', 'domain']:
name_order = name_list[3] if name_list[3:4] else name_order resource_root = parts.pop(0)
name = '{0}/m/{2}'.format(*name_list)
elif len(name_list) == 1 and name_list[0] != '':
name = name_list[0]
else: else:
resource_root = 'r'
# There should at most two parts left, the resource and the order
if len(parts) == 1:
resource, resource_order = parts[0], None
elif len(parts) == 2:
resource, resource_order = parts
else:
raise InvalidSubreddit()
if not resource:
# Praw does not correctly handle empty strings # Praw does not correctly handle empty strings
# https://github.com/praw-dev/praw/issues/615 # https://github.com/praw-dev/praw/issues/615
raise InvalidSubreddit() raise InvalidSubreddit()
order = order or name_order # If the order was explicitly passed in, it will take priority over
listing = 'u' if name == 'me' else listing # the order that was extracted from the name
display_name = '/{0}/{1}'.format(listing, name) order = order or resource_order
time = {t: '_from_' + t for t in ['all', 'day', 'hour', display_order = order
'month', 'week', 'year']} display_name = '/'.join(['', resource_root, resource])
time[None] = ''
if period not in time.keys(): # Split the order from the period E.g. controversial-all, top-hour
raise exceptions.SubredditError('Unrecognized period "%s"' if order and '-' in order:
% period) order, period = order.split('-', 1)
else:
period = None
elif order not in ['hot', 'top', 'rising', 'new', if order not in ['hot', 'top', 'rising', 'new', 'controversial', None]:
'controversial', None]: raise InvalidSubreddit('Invalid order "%s"' % order)
raise exceptions.SubredditError('Unrecognized order "%s"' % order) if period not in ['all', 'day', 'hour', 'month', 'week', 'year', None]:
raise InvalidSubreddit('Invalid period "%s"' % period)
if period and order not in ['top', 'controversial']:
raise InvalidSubreddit('"%s" order does not allow sorting by'
'period' % order)
# On some objects, praw doesn't allow you to pass arguments for the
# order and period. Instead you need to call special helper functions
# such as Multireddit.get_controversial_from_year(). Build the method
# name here for convenience.
if period:
method_alias = 'get_{0}_from_{1}'.format(order, period)
elif order:
method_alias = 'get_{0}'.format(order)
else:
method_alias = 'get_hot'
# Here's where we start to build the submission generators
if query: if query:
if listing in ['u', 'user'] and '/m/' not in name: if resource_root in ('u', 'user'):
reddit.config.API_PATHS['search'] = 'r/{subreddit}/search' search = '/r/{subreddit}/search'
if name == 'me' and reddit.is_oauth_session(): author = reddit.user.name if resource == 'me' else resource
query = 'author:{0} {1}'.format(reddit.get_me().name, query) query = 'author:{0} {1}'.format(author, query)
else: subreddit = None
query = 'author:{0} {1}'.format(name, query)
location = None
else: else:
reddit.config.API_PATHS['search'] = \ search = resource_root + '/{{subreddit}}/search'
'{}/{{subreddit}}/search'.format(listing) subreddit = None if resource == 'front' else resource
location = None if name == 'front' else name
submissions = reddit.search(query, subreddit=location, sort=order, reddit.config.API_PATHS['search'] = search
period=period) submissions = reddit.search(query, subreddit=subreddit,
sort=order, period=period)
elif resource_root == 'domain':
order = order or 'hot'
submissions = reddit.get_domain_listing(
resource, sort=order, period=period, limit=None)
elif listing == 'domain': elif resource_root.endswith('/m'):
submissions = reddit.get_domain_listing(name, redditor, _, multi = resource_root.split('/')
sort=(order or 'hot'), period=period) multireddit = reddit.get_multireddit(redditor, multi)
submissions = getattr(multireddit, method_alias)(limit=None)
elif listing in ['u', 'user']: elif resource_root in ('u', 'user') and resource == 'me':
if '/m/' in name: if not reddit.is_oauth_session():
multireddit = reddit.get_multireddit(*name.split('/')[::2]) raise exceptions.AccountError('Not logged in')
if order in ['top', 'controversial']:
submissions = eval('multireddit.get_{0}{1}(limit=None)' \
.format((order), time[period]))
else:
submissions = eval('multireddit.get_{0}(limit=None)' \
.format((order or 'hot')))
elif name == 'me':
if not reddit.is_oauth_session():
raise exceptions.AccountError('Not logged in')
else:
submissions = reddit.user.get_submitted( \
sort=(order or 'new'))
else: else:
redditor = reddit.get_redditor(name) order = order or 'new'
submissions = redditor.get_submitted(sort=(order or 'new'), submissions = reddit.user.get_submitted(sort=order, limit=None)
time=(period or 'all'))
elif listing == 'r': elif resource_root in ('u', 'user'):
if name == 'front': order = order or 'new'
dispatch = { period = period or 'all'
None: reddit.get_front_page, redditor = reddit.get_redditor(resource)
'hot': reddit.get_front_page, submissions = redditor.get_submitted(
'top': eval('reddit.get_top' + time[period]), sort=order, time=period, limit=None)
'rising': reddit.get_rising,
'new': reddit.get_new,
'controversial': eval('reddit.get_controversial' \
+ time[period]),
}
elif resource == 'front':
if order in (None, 'hot'):
submissions = reddit.get_front_page(limit=None)
else: else:
subreddit = reddit.get_subreddit(name) submissions = getattr(reddit, method_alias)(limit=None)
# For special subreddits like /r/random we want to replace the
# display name with the one returned by the request.
display_name = '/r/{0}'.format(subreddit.display_name)
dispatch = {
None: subreddit.get_hot,
'hot': subreddit.get_hot,
'top': eval('subreddit.get_top' + time[period]),
'rising': subreddit.get_rising,
'new': subreddit.get_new,
'controversial': eval('subreddit.get_controversial' \
+ time[period]),
}
submissions = dispatch[order](limit=None)
return cls(display_name, submissions, loader, order=order, else:
listing=listing, period=period) subreddit = reddit.get_subreddit(resource)
submissions = getattr(subreddit, method_alias)(limit=None)
# For special subreddits like /r/random we want to replace the
# display name with the one returned by the request.
display_name = '/r/{0}'.format(subreddit.display_name)
# We made it!
return cls(display_name, submissions, loader, order=display_order)
def get(self, index, n_cols=70): def get(self, index, n_cols=70):
""" """

View File

@@ -323,7 +323,8 @@ class Page(object):
text = spacing.join(items) text = spacing.join(items)
self.term.add_line(window, text, 0, 0) self.term.add_line(window, text, 0, 0)
if self.content.order is not None: if self.content.order is not None:
col = text.find(self.content.order) - 3 order = self.content.order.split('-')[0]
col = text.find(order) - 3
window.chgat(0, col, 3, attr | curses.A_REVERSE) window.chgat(0, col, 3, attr | curses.A_REVERSE)
self._row += 1 self._row += 1

View File

@@ -18,8 +18,8 @@ class SubscriptionPage(Page):
super(SubscriptionPage, self).__init__(reddit, term, config, oauth) super(SubscriptionPage, self).__init__(reddit, term, config, oauth)
self.controller = SubscriptionController(self, keymap=config.keymap) self.controller = SubscriptionController(self, keymap=config.keymap)
self.content = SubscriptionContent.from_user(reddit, term.loader, self.content = SubscriptionContent.from_user(
content_type) reddit, term.loader, content_type)
self.nav = Navigator(self.content.get) self.nav = Navigator(self.content.get)
self.content_type = content_type self.content_type = content_type
self.subreddit_data = None self.subreddit_data = None