Skip to content

Commit

Permalink
Adds the "subreddit" parameter to Reddit.info(). (#1570)
Browse files Browse the repository at this point in the history
This change adds the `subreddit` parameter as defined in the reddit API documentation (https://www.reddit.com/dev/api#GET_api_info). This change was implemented in the Reddit API earlier today, which makes it easier for developers to get many subreddits at once by their name, which can significantly reduce the amount of requests made by an API client.

This change adds the parameter to info, updates relevant checks, and updates the test that test for IDs provided. Previously, if developers wanted to use this new parameter they would have to perform the request manually.

In accordance with some contributing guidelines, this commit adds the two integration tests needed.

The test uses one subreddit name that is normally formatted (/r/redditdev) and three others, which while are still valid subreddits, are different from the norm in some way (/r/nl's name is too short, /r/t:1337 is a timereddit which has a colon in its subreddit name, and /r/reddit.com which has a period in its name.

Each subreddit exists and is publicly accessible, which should make tests that use these subreddit succeed for the forseeable future. If the visibility of any of the subreddits do change, the test may have to be changed to reflect this.

(cherry picked from 0e57527d3f5ccc0279f6b0c21b310b1f607f8152)
  • Loading branch information
jkrejcha authored and LilSpazJoekp committed Jan 25, 2021
1 parent c636604 commit 922142d
Show file tree
Hide file tree
Showing 6 changed files with 146 additions and 14 deletions.
1 change: 1 addition & 0 deletions AUTHORS.rst
Expand Up @@ -68,5 +68,6 @@ Source Contributors
- Todd Roberts `@toddrob99 <https://github.com/toddrob99>`_
- MaybeNetwork `@MaybeNetwork <https://github.com/MaybeNetwork>`_
- Nick Kelly `@nickatnight <https://github.com/nickatnight>`_
- Justin Krejcha <justin@justinkrejcha.com> `@jkrejcha <https://github.com/jkrejcha>`_
- Gerard Rodes <GerardRodesVidal@gmail.com> `@GerardRodes <https://github.com/GerardRodes>`_
<!-- - Add "Name <email (optional)> and github profile link" above this line. -->
2 changes: 2 additions & 0 deletions CHANGES.rst
Expand Up @@ -13,6 +13,8 @@ Unreleased
* Add method :meth:`.invited` to get invited moderators of a subreddit.
* Add method :meth:`~.Submission.award` and :meth:`~.Comment.award` with the ability to
specify type of award, anonymity, and message when awarding a submission or comment.
* Ability to specify subreddits by name using the `subreddits` parameter in
:meth:`.Reddit.info`.
* Ability to submit text/self posts with inline media.
* Added :meth:`.Reddit.close` to close the requestor session.
* Ability to use :class:`.Reddit` as an asynchronous context manager that automatically
Expand Down
36 changes: 24 additions & 12 deletions asyncpraw/reddit.py
Expand Up @@ -555,13 +555,16 @@ def info(
self,
fullnames: Optional[Iterable[str]] = None,
url: Optional[str] = None,
subreddits: Optional[Iterable[Union[Subreddit, str]]] = None,
) -> AsyncGenerator[Union[Subreddit, Comment, Submission], None]:
"""Fetch information about each item in ``fullnames`` or from ``url``.
"""Fetch information about each item in ``fullnames``, ``url``, or ``subreddits``.
:param fullnames: A list of fullnames for comments, submissions, and/or
subreddits.
:param url: A url (as a string) to retrieve lists of link submissions
from.
:param subreddits: A list of subreddit names or Subreddit objects to retrieve
subreddits from.
:returns: A generator that yields found items in their relative order.
Items that cannot be matched will not be generated. Requests will be
Expand All @@ -577,24 +580,33 @@ def info(
different set of submissions.
"""
none_count = (fullnames, url).count(None)
if none_count > 1:
raise TypeError("Either `fullnames` or `url` must be provided.")
if none_count < 1:
raise TypeError("Mutually exclusive parameters: `fullnames`, `url`")
none_count = (fullnames, url, subreddits).count(None)
if none_count != 2:
raise TypeError(
"Either `fullnames`, `url`, or `subreddits` must be provided."
)

is_using_fullnames = fullnames is not None
ids_or_names = fullnames if is_using_fullnames else subreddits

if fullnames is not None:
if isinstance(fullnames, str):
raise TypeError("`fullnames` must be a non-str iterable.")
if ids_or_names is not None:
if isinstance(ids_or_names, str):
raise TypeError(
"`fullnames` and `subreddits` must be a non-str iterable."
)

api_parameter_name = "id" if is_using_fullnames else "sr_name"

async def generator(fullnames):
iterable = iter(fullnames)
if is_using_fullnames:
iterable = iter(ids_or_names)
else:
iterable = iter([str(item) for item in ids_or_names])
while True:
chunk = list(islice(iterable, 100))
if not chunk:
break

params = {"id": ",".join(chunk)}
params = {api_parameter_name: ",".join(chunk)}
for result in await self.get(API_PATH["info"], params=params):
yield result

Expand Down
107 changes: 107 additions & 0 deletions tests/integration/cassettes/TestReddit.test_info_sr_names.json

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions tests/integration/test_reddit.py
Expand Up @@ -7,6 +7,7 @@
from asyncpraw.models import LiveThread
from asyncpraw.models.reddit.base import RedditBase
from asyncpraw.models.reddit.submission import Submission
from asyncpraw.models.reddit.subreddit import Subreddit

from . import IntegrationTest

Expand Down Expand Up @@ -46,6 +47,15 @@ async def test_info_url(self):
for item in results:
assert isinstance(item, Submission)

async def test_info_sr_names(self):
items = [await self.reddit.subreddit("redditdev"), "reddit.com", "t:1337", "nl"]
item_generator = self.reddit.info(subreddits=items)
with self.use_cassette():
results = await self.async_list(item_generator)
assert len(results) == 4
for item in results:
assert isinstance(item, Subreddit)

@mock.patch("asyncio.sleep", return_value=None)
async def test_live_call(self, _):
thread_id = "ukaeu1ik4sw5"
Expand Down
4 changes: 2 additions & 2 deletions tests/unit/test_reddit.py
Expand Up @@ -40,13 +40,13 @@ def test_info__invalid_param(self):
with pytest.raises(TypeError) as excinfo:
self.reddit.info(None)

err_str = "Either `fullnames` or `url` must be provided."
err_str = "Either `fullnames`, `url`, or `subreddits` must be provided."
assert str(excinfo.value) == err_str

with pytest.raises(TypeError) as excinfo:
self.reddit.info([], "")

assert excinfo.match("(?i)mutually exclusive")
assert str(excinfo.value) == err_str

def test_invalid_config(self):
with pytest.raises(ValueError) as excinfo:
Expand Down

0 comments on commit 922142d

Please sign in to comment.