From 3db321f55177983308f6e1b6766c05ff3bdd2d05 Mon Sep 17 00:00:00 2001 From: LilSpazJoekp <15524072+LilSpazJoekp@users.noreply.github.com> Date: Wed, 24 Feb 2021 23:58:28 -0600 Subject: [PATCH] Format docs with docstrfmt --- AUTHORS.rst | 16 +- CHANGES.rst | 64 +- README.rst | 112 +- asyncpraw/__init__.py | 11 +- asyncpraw/exceptions.py | 49 +- asyncpraw/models/auth.py | 65 +- asyncpraw/models/base.py | 7 +- asyncpraw/models/comment_forest.py | 79 +- asyncpraw/models/helpers.py | 99 +- asyncpraw/models/inbox.py | 40 +- asyncpraw/models/list/trophy.py | 4 +- asyncpraw/models/listing/generator.py | 21 +- asyncpraw/models/listing/mixins/base.py | 96 +- asyncpraw/models/listing/mixins/redditor.py | 12 +- asyncpraw/models/listing/mixins/submission.py | 4 +- asyncpraw/models/preferences.py | 49 +- asyncpraw/models/reddit/base.py | 1 + asyncpraw/models/reddit/collections.py | 115 +- asyncpraw/models/reddit/comment.py | 149 +- asyncpraw/models/reddit/emoji.py | 73 +- asyncpraw/models/reddit/live.py | 255 ++-- asyncpraw/models/reddit/message.py | 103 +- asyncpraw/models/reddit/mixins/__init__.py | 90 +- asyncpraw/models/reddit/mixins/editable.py | 1 + asyncpraw/models/reddit/mixins/fullname.py | 4 +- asyncpraw/models/reddit/mixins/gildable.py | 2 + asyncpraw/models/reddit/mixins/inboxable.py | 40 +- .../models/reddit/mixins/inboxtoggleable.py | 8 +- asyncpraw/models/reddit/mixins/messageable.py | 5 +- asyncpraw/models/reddit/mixins/replyable.py | 26 +- asyncpraw/models/reddit/mixins/savable.py | 13 +- asyncpraw/models/reddit/mixins/votable.py | 44 +- asyncpraw/models/reddit/modmail.py | 102 +- asyncpraw/models/reddit/multi.py | 99 +- asyncpraw/models/reddit/poll.py | 80 +- asyncpraw/models/reddit/redditor.py | 156 +- asyncpraw/models/reddit/removal_reasons.py | 64 +- asyncpraw/models/reddit/rules.py | 129 +- asyncpraw/models/reddit/submission.py | 271 ++-- asyncpraw/models/reddit/subreddit.py | 1229 ++++++++-------- asyncpraw/models/reddit/widgets.py | 1283 +++++++++-------- asyncpraw/models/reddit/wikipage.py | 75 +- asyncpraw/models/redditors.py | 10 +- asyncpraw/models/stylesheet.py | 22 +- asyncpraw/models/subreddits.py | 20 +- asyncpraw/models/trophy.py | 42 +- asyncpraw/models/user.py | 58 +- asyncpraw/models/util.py | 71 +- asyncpraw/objector.py | 11 +- asyncpraw/reddit.py | 256 ++-- asyncpraw/util/cache.py | 19 +- asyncpraw/util/token_manager.py | 8 +- docs/code_overview/asyncpraw_models.rst | 26 +- docs/code_overview/exceptions.rst | 7 +- docs/code_overview/models/comment.rst | 2 +- docs/code_overview/models/livethread.rst | 2 +- docs/code_overview/models/liveupdate.rst | 2 +- docs/code_overview/models/message.rst | 2 +- .../models/modmailconversation.rst | 2 +- docs/code_overview/models/more.rst | 2 +- docs/code_overview/models/multireddit.rst | 2 +- docs/code_overview/models/redditor.rst | 2 +- docs/code_overview/models/submission.rst | 2 +- docs/code_overview/models/subreddit.rst | 2 +- docs/code_overview/models/wikipage.rst | 2 +- docs/code_overview/other.rst | 206 +-- docs/code_overview/other/auth.rst | 2 +- docs/code_overview/other/button.rst | 3 +- docs/code_overview/other/buttonwidget.rst | 3 +- docs/code_overview/other/calendar.rst | 3 +- .../other/calendarconfiguration.rst | 3 +- docs/code_overview/other/collection.rst | 3 +- .../other/collectionmoderation.rst | 3 +- docs/code_overview/other/commentforest.rst | 2 +- docs/code_overview/other/commenthelper.rst | 2 +- .../code_overview/other/commentmoderation.rst | 2 +- docs/code_overview/other/communitylist.rst | 3 +- docs/code_overview/other/config.rst | 2 +- .../other/contributorrelationship.rst | 2 +- docs/code_overview/other/customwidget.rst | 3 +- docs/code_overview/other/domainlisting.rst | 2 +- docs/code_overview/other/emoji.rst | 2 +- docs/code_overview/other/hover.rst | 3 +- docs/code_overview/other/idcard.rst | 3 +- docs/code_overview/other/image.rst | 2 +- docs/code_overview/other/imagedata.rst | 2 +- docs/code_overview/other/imagewidget.rst | 3 +- docs/code_overview/other/inlinegif.rst | 2 +- docs/code_overview/other/inlineimage.rst | 2 +- docs/code_overview/other/inlinemedia.rst | 2 +- docs/code_overview/other/inlinevideo.rst | 2 +- docs/code_overview/other/listinggenerator.rst | 2 +- .../other/livecontributorrelationship.rst | 2 +- .../other/livethreadcontribution.rst | 2 +- docs/code_overview/other/livethreadstream.rst | 2 +- .../other/liveupdatecontribution.rst | 2 +- docs/code_overview/other/menu.rst | 2 +- docs/code_overview/other/menulink.rst | 2 +- docs/code_overview/other/mod_action.rst | 2 +- .../other/moderatorrelationship.rst | 2 +- docs/code_overview/other/moderatorswidget.rst | 3 +- docs/code_overview/other/modmail.rst | 2 +- docs/code_overview/other/modmailmessage.rst | 2 +- docs/code_overview/other/poll.rst | 4 +- docs/code_overview/other/postflairwidget.rst | 2 +- docs/code_overview/other/preferences.rst | 2 +- docs/code_overview/other/redditbase.rst | 2 +- docs/code_overview/other/redditorlist.rst | 2 +- docs/code_overview/other/redditorstream.rst | 2 +- docs/code_overview/other/removalreason.rst | 2 +- docs/code_overview/other/rule.rst | 2 +- docs/code_overview/other/rulemoderation.rst | 2 +- docs/code_overview/other/ruleswidget.rst | 3 +- docs/code_overview/other/styles.rst | 3 +- docs/code_overview/other/stylesheet.rst | 2 +- docs/code_overview/other/sublisting.rst | 2 +- docs/code_overview/other/submenu.rst | 2 +- docs/code_overview/other/submissionflair.rst | 2 +- .../other/submissionmoderation.rst | 2 +- .../other/subredditcollections.rst | 3 +- .../other/subredditcollectionsmoderation.rst | 3 +- docs/code_overview/other/subredditemoji.rst | 2 +- docs/code_overview/other/subredditfilters.rst | 2 +- docs/code_overview/other/subredditflair.rst | 2 +- .../other/subredditflairtemplates.rst | 2 +- .../other/subredditlinkflairtemplates.rst | 2 +- docs/code_overview/other/subredditmessage.rst | 2 +- .../other/subredditmoderation.rst | 2 +- .../other/subredditmoderationstream.rst | 2 +- .../other/subredditquarantine.rst | 2 +- .../other/subredditredditorflairtemplates.rst | 2 +- .../other/subredditrelationship.rst | 2 +- .../other/subredditremovalreasons.rst | 2 +- docs/code_overview/other/subredditrules.rst | 2 +- .../other/subredditrulesmoderation.rst | 2 +- docs/code_overview/other/subredditstream.rst | 2 +- .../other/subredditstylesheet.rst | 2 +- docs/code_overview/other/subredditwidgets.rst | 2 +- .../other/subredditwidgetsmoderation.rst | 2 +- docs/code_overview/other/subredditwiki.rst | 2 +- docs/code_overview/other/textarea.rst | 3 +- .../other/thingmoderationmixin.rst | 2 +- docs/code_overview/other/token_manager.rst | 2 +- docs/code_overview/other/trophy.rst | 3 +- docs/code_overview/other/util.rst | 4 +- docs/code_overview/other/widgetmoderation.rst | 2 +- .../other/wikipagemoderation.rst | 2 +- docs/code_overview/reddit/front.rst | 2 +- docs/code_overview/reddit/inbox.rst | 2 +- docs/code_overview/reddit/live.rst | 2 +- docs/code_overview/reddit/multireddit.rst | 2 +- docs/code_overview/reddit/redditors.rst | 2 +- docs/code_overview/reddit/subreddit.rst | 2 +- docs/code_overview/reddit/subreddits.rst | 2 +- docs/code_overview/reddit/user.rst | 2 +- docs/code_overview/reddit_instance.rst | 22 +- docs/getting_started/authentication.rst | 239 +-- docs/getting_started/configuration.rst | 94 +- .../configuration/environment_variables.rst | 16 +- .../getting_started/configuration/options.rst | 140 +- .../getting_started/configuration/prawini.rst | 177 +-- .../configuration/reddit_initialization.rst | 25 +- docs/getting_started/faq.rst | 40 +- docs/getting_started/installation.rst | 37 +- docs/getting_started/logging.rst | 37 +- docs/getting_started/multiple_instances.rst | 29 +- docs/getting_started/quick_start.rst | 261 ++-- docs/index.rst | 78 +- docs/package_info/asyncpraw_migration.rst | 42 +- docs/package_info/contributing.rst | 135 +- docs/package_info/glossary.rst | 41 +- docs/package_info/praw7_migration.rst | 43 +- docs/package_info/references.rst | 33 +- docs/tutorials/comments.rst | 131 +- docs/tutorials/refresh_token.rst | 27 +- docs/tutorials/reply_bot.rst | 221 ++- pre_push.py | 12 +- tests/conftest.py | 3 +- tests/integration/__init__.py | 1 + tests/integration/test_github_actions.py | 5 +- tools/check_documentation.py | 8 +- tools/static_word_checks.py | 21 +- 182 files changed, 4069 insertions(+), 3972 deletions(-) diff --git a/AUTHORS.rst b/AUTHORS.rst index cbbee5e5b..8201d5d75 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -3,7 +3,6 @@ Author/Maintainer - Joel Payne `@LilSpazJoekp `_ - Documentation Contributors ========================== @@ -24,19 +23,16 @@ Documentation Contributors - PRAW Author =========== - Bryce Boe `@bboe `_ - Logo Creator ============ - kungming2 `@kungming2 `_ - Source Contributors =================== @@ -55,9 +51,11 @@ Source Contributors - Andrew Arnold `@asquared31415 `_ - bakonydraco `@bakonydraco `_ - salehio `@salehio `_ -- Amanda O'Neal `@amandaoneal `_ +- Amanda O'Neal `@amandaoneal + `_ - Gourari Oussama `@O-Gourari `_ -- Declan Hoare `@NetwideRogue `_ +- Declan Hoare `@NetwideRogue + `_ - Elaina Martineau `@CrackedP0t `_ - Rob Curtis `@waab76 `_ - Pyprohly `@Pyprohly `_ @@ -68,14 +66,16 @@ Source Contributors - Jack Steel `@jackodsteel `_ - David Mirch `@fwump38 `_ - PythonCoderAS `@PythonCoderAS `_ -- Michael Cetrulo `@git2samus `_ +- Michael Cetrulo `@git2samus + `_ - George Schizas `@gschizas `_ - Todd Roberts `@toddrob99 `_ - MaybeNetwork `@MaybeNetwork `_ - Nick Kelly `@nickatnight `_ - Yash Chhabria `@Cyatos `_ - Justin Krejcha `@jkrejcha `_ -- Gerard Rodes `@GerardRodes `_ +- Gerard Rodes `@GerardRodes + `_ - cmays90 `@cmays90 `_ diff --git a/CHANGES.rst b/CHANGES.rst index 7b9cdc7a5..988642125 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -6,19 +6,19 @@ Unreleased **Added** -* :class:`.Reddit` keyword argument ``token_manager``. -* :class:`.FileTokenManager` and its parent abstract class :class:`.BaseTokenManager`. +- :class:`.Reddit` keyword argument ``token_manager``. +- :class:`.FileTokenManager` and its parent abstract class :class:`.BaseTokenManager`. **Deprecated** -* The configuration setting ``refresh_token`` is deprecated and its use will result in a +- The configuration setting ``refresh_token`` is deprecated and its use will result in a :py:class:`DeprecationWarning`. This deprecation applies in all ways of setting configuration values, i.e., via ``praw.ini``, as a keyword argument when initializing an instance of :class:`.Reddit`, and via the ``PRAW_REFRESH_TOKEN`` environment variable. To be prepared for Async PRAW 8, use the new :class:`.Reddit` keyword argument ``token_manager``. See :ref:`refresh_token` in Async PRAW's documentation for an example. -* :meth:`.me` will no longer return ``None`` when called in :attr:`.read_only` mode +- :meth:`.me` will no longer return ``None`` when called in :attr:`.read_only` mode starting in Async PRAW 8. A :py:class:`DeprecationWarning` will be issued. To switch forward to the Async PRAW 8 behavior set ``praw8_raise_exception_on_me=True`` in your ``asyncpraw.Reddit(...)`` call. @@ -28,56 +28,54 @@ Unreleased **Added** -* Add method :meth:`~.Subreddits.premium` to reflect the naming change in Reddit's API. -* Ability to submit image galleries with :meth:`.submit_gallery`. -* Ability to pass a gallery url to :meth:`.Reddit.submission`. -* Ability to specify modmail mute duration. -* Add method :meth:`.invited` to get invited moderators of a subreddit. -* Ability to submit text/self posts with inline media. -* Add method :meth:`~.Submission.award` and :meth:`~.Comment.award` with the ability to +- Add method :meth:`~.Subreddits.premium` to reflect the naming change in Reddit's API. +- Ability to submit image galleries with :meth:`.submit_gallery`. +- Ability to pass a gallery url to :meth:`.Reddit.submission`. +- Ability to specify modmail mute duration. +- Add method :meth:`.invited` to get invited moderators of a subreddit. +- Ability to submit text/self posts with inline media. +- 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 +- Ability to specify subreddits by name using the `subreddits` parameter in :meth:`.Reddit.info`. -* Added :meth:`.Reddit.close` to close the requestor session. -* Ability to use :class:`.Reddit` as an asynchronous context manager that automatically +- Added :meth:`.Reddit.close` to close the requestor session. +- Ability to use :class:`.Reddit` as an asynchronous context manager that automatically closes the requestor session on exit. **Changed** -* :class:`~.BoundedSet` will now utilize a Last-Recently-Used (LRU) storing mechanism, +- :class:`~.BoundedSet` will now utilize a Last-Recently-Used (LRU) storing mechanism, which will change the order in which elements are removed from the set. -* Improved :meth:`.submit_image` and :meth:`.submit_video` performance in slow - network environments by removing a race condition when establishing a - websocket connection. +- Improved :meth:`.submit_image` and :meth:`.submit_video` performance in slow network + environments by removing a race condition when establishing a websocket connection. **Deprecated** -* :meth:`~.Subreddits.gold` is superseded by :meth:`~.Subreddits.premium`. -* :meth:`~.Submission.gild` is superseded by :meth:`~.Submission.award`. -* :meth:`~.Comment.gild` is superseded by :meth:`~.Comment.award`. -* ``PRAWException`` is superseded by :class:`.AsyncPRAWException`. +- :meth:`~.Subreddits.gold` is superseded by :meth:`~.Subreddits.premium`. +- :meth:`~.Submission.gild` is superseded by :meth:`~.Submission.award`. +- :meth:`~.Comment.gild` is superseded by :meth:`~.Comment.award`. +- ``PRAWException`` is superseded by :class:`.AsyncPRAWException`. **Fixed** -* An issue where leaving as a moderator fails if you are using token auth. -* An issue where an incorrect error was being raised due to invalid submission urls. -* A bug where if you call `.parent()` on a comment it clears its replies. -* An issue where performing a deepcopy on an :class:`.RedditBase` object will fail. -* Some cases where streams yield the same item multiple times. This cannot be - prevented in every case. -* An issue where streams could get stuck on a deleted item and never pull new items. -* Fix subreddit style asset uploading. +- An issue where leaving as a moderator fails if you are using token auth. +- An issue where an incorrect error was being raised due to invalid submission urls. +- A bug where if you call `.parent()` on a comment it clears its replies. +- An issue where performing a deepcopy on an :class:`.RedditBase` object will fail. +- Some cases where streams yield the same item multiple times. This cannot be prevented + in every case. +- An issue where streams could get stuck on a deleted item and never pull new items. +- Fix subreddit style asset uploading. 7.1.0 (2020/07/16) ------------------ -* First official Async PRAW release! +- First official Async PRAW release! 7.1.0.pre1 (2020/07/16) ----------------------- -* Initial Async PRAW pre release. - +- Initial Async PRAW pre release. For changes in PRAW please see: `PRAW Changelog `_ diff --git a/README.rst b/README.rst index 03d1184b1..9809d3fcc 100644 --- a/README.rst +++ b/README.rst @@ -2,38 +2,43 @@ Async PRAW: The Asynchronous Python Reddit API Wrapper ====================================================== .. image:: https://img.shields.io/pypi/v/asyncpraw.svg - :alt: Latest asyncpraw Version - :target: https://pypi.python.org/pypi/asyncpraw + :alt: Latest asyncpraw Version + :target: https://pypi.python.org/pypi/asyncpraw + .. image:: https://img.shields.io/pypi/pyversions/asyncpraw - :alt: Supported Python Versions - :target: https://pypi.python.org/pypi/asyncpraw + :alt: Supported Python Versions + :target: https://pypi.python.org/pypi/asyncpraw + .. image:: https://img.shields.io/pypi/dm/asyncpraw - :alt: PyPI - Downloads - Monthly - :target: https://pypi.python.org/pypi/asyncpraw + :alt: PyPI - Downloads - Monthly + :target: https://pypi.python.org/pypi/asyncpraw + .. image:: https://coveralls.io/repos/github/praw-dev/asyncpraw/badge.svg?branch=master - :alt: Coveralls Coverage - :target: https://coveralls.io/github/praw-dev/asyncpraw?branch=master + :alt: Coveralls Coverage + :target: https://coveralls.io/github/praw-dev/asyncpraw?branch=master + .. image:: https://github.com/praw-dev/asyncpraw/workflows/CI/badge.svg - :alt: Github Actions Coverage - :target: https://github.com/praw-dev/asyncpraw/actions?query=branch%3Amaster + :alt: Github Actions Coverage + :target: https://github.com/praw-dev/asyncpraw/actions?query=branch%3Amaster + .. image:: https://img.shields.io/badge/Contributor%20Covenant-v2.0%20adopted-ff69b4.svg - :alt: Contributor Covenant - :target: https://github.com/praw-dev/asyncpraw/blob/master/CODE_OF_CONDUCT.md + :alt: Contributor Covenant + :target: https://github.com/praw-dev/asyncpraw/blob/master/CODE_OF_CONDUCT.md -Async PRAW, an abbreviation for "Asynchronous Python Reddit API Wrapper", is a Python package that -allows for simple access to Reddit's API. Async PRAW aims to be easy to use and -internally follows all of `Reddit's API rules +Async PRAW, an abbreviation for "Asynchronous Python Reddit API Wrapper", is a Python +package that allows for simple access to Reddit's API. Async PRAW aims to be easy to use +and internally follows all of `Reddit's API rules `_. With Async PRAW there's no need to -introduce ``sleep`` calls in your code. Give your client an appropriate user -agent and you're set. +introduce ``sleep`` calls in your code. Give your client an appropriate user agent and +you're set. .. _installation: Installation ------------ -Async PRAW is supported on Python 3.6+. The recommended way to -install Async PRAW is via `pip `_. +Async PRAW is supported on Python 3.6+. The recommended way to install Async PRAW is via +`pip `_. .. code-block:: bash @@ -45,22 +50,26 @@ To install the latest development version of Async PRAW run the following instea pip install --upgrade https://github.com/praw-dev/asyncpraw/archive/master.zip -For instructions on installing Python and pip see "The Hitchhiker's Guide to -Python" `Installation Guides -`_. +For instructions on installing Python and pip see "The Hitchhiker's Guide to Python" +`Installation Guides `_. Quickstart ---------- -Assuming you already have a credentials for a script-type OAuth application you -can instantiate an instance of Async PRAW like so: +Assuming you already have a credentials for a script-type OAuth application you can +instantiate an instance of Async PRAW like so: .. code-block:: python import asyncpraw - reddit = asyncpraw.Reddit(client_id="CLIENT_ID", client_secret="CLIENT_SECRET", - password="PASSWORD", user_agent="USERAGENT", - username="USERNAME") + + reddit = asyncpraw.Reddit( + client_id="CLIENT_ID", + client_secret="CLIENT_SECRET", + password="PASSWORD", + user_agent="USERAGENT", + username="USERNAME", + ) With the ``reddit`` instance you can then interact with Reddit: @@ -71,7 +80,9 @@ With the ``reddit`` instance you can then interact with Reddit: await subreddit.submit("Test Submission", url="https://reddit.com") # Comment on a known submission - submission = await reddit.submission(url="https://www.reddit.com/comments/5e1az9", lazy=True) + submission = await reddit.submission( + url="https://www.reddit.com/comments/5e1az9", lazy=True + ) await submission.reply("Super rad!") # Reply to the first comment of a weekly top thread of a moderated community @@ -89,41 +100,43 @@ With the ``reddit`` instance you can then interact with Reddit: async for moderator in subreddit.moderator: print(moderator) -Please see Async PRAW's `documentation `_ for -more examples of what you can do with Async PRAW. +Please see Async PRAW's `documentation `_ for more +examples of what you can do with Async PRAW. Async PRAW Discussion and Support --------------------------------- -For those new to Python, or would otherwise consider themselves a Python -beginner, please consider asking questions on the `r/learnpython -`_ subreddit. There are wonderful people -there who can help with general Python and simple Async PRAW related questions. +For those new to Python, or would otherwise consider themselves a Python beginner, +please consider asking questions on the `r/learnpython +`_ subreddit. There are wonderful people there who +can help with general Python and simple Async PRAW related questions. Otherwise, there are a few official places to ask questions about Async PRAW: -`r/redditdev `_ is the best place on -Reddit to ask Async PRAW related questions. This subreddit is for all Reddit API -related discussion so please tag submissions with *[Async PRAW]*. Please perform a -search on the subreddit first to see if anyone has similar questions. +`r/redditdev `_ is the best place on Reddit to ask +Async PRAW related questions. This subreddit is for all Reddit API related discussion so +please tag submissions with *[Async PRAW]*. Please perform a search on the subreddit +first to see if anyone has similar questions. Real-time chat can be conducted via the `PRAW Slack Organization `_ (please create an issue if that invite link has expired). -Please do not directly message any of the contributors via Reddit, email, or -Slack unless they have indicated otherwise. We strongly encourage everyone to -help others with their questions. +Please do not directly message any of the contributors via Reddit, email, or Slack +unless they have indicated otherwise. We strongly encourage everyone to help others with +their questions. Please file bugs and feature requests as issues on `GitHub `_ after first searching to ensure a -similar issue was not already filed. If such an issue already exists please -give it a thumbs up reaction. Comments to issues containing additional -information are certainly welcome. +similar issue was not already filed. If such an issue already exists please give it a +thumbs up reaction. Comments to issues containing additional information are certainly +welcome. + +.. note:: -.. note:: This project is released with a `Contributor Code of Conduct - `_. By - participating in this project you agree to abide by its terms. + This project is released with a `Contributor Code of Conduct + `_. By + participating in this project you agree to abide by its terms. Documentation ------------- @@ -135,7 +148,8 @@ History `February 2019 `_: -Joel forked PRAW and began work on Async PRAW, an asynchronous compatible version of PRAW. +Joel forked PRAW and began work on Async PRAW, an asynchronous compatible version of +PRAW. `July 2020 `_: @@ -147,4 +161,4 @@ License Async PRAW's source (v7.1.1+) is provided under the `Simplified BSD License `_. -* Copyright ©, 2020, Joel Payne +- Copyright ©, 2020, Joel Payne diff --git a/asyncpraw/__init__.py b/asyncpraw/__init__.py index 550bd2acf..098888d46 100644 --- a/asyncpraw/__init__.py +++ b/asyncpraw/__init__.py @@ -1,12 +1,13 @@ """Asynchronous Python Reddit API Wrapper. -Async PRAW, an abbreviation for "Asynchronous Python Reddit API Wrapper", is a python package that -allows for simple access to reddit's API. Async PRAW aims to be as easy to use as -possible and is designed to follow all of reddit's API rules. You have to give -a useragent, everything else is handled by Async PRAW so you needn't worry about -violating them. +Async PRAW, an abbreviation for "Asynchronous Python Reddit API Wrapper", is a python +package that allows for simple access to reddit's API. Async PRAW aims to be as easy to +use as possible and is designed to follow all of reddit's API rules. You have to give a +useragent, everything else is handled by Async PRAW so you needn't worry about violating +them. More information about Async PRAW can be found at https://github.com/praw-dev/asyncpraw + """ from .const import __version__ # NOQA diff --git a/asyncpraw/exceptions.py b/asyncpraw/exceptions.py index c8ed8e739..03052f281 100644 --- a/asyncpraw/exceptions.py +++ b/asyncpraw/exceptions.py @@ -1,9 +1,8 @@ """Async PRAW exception classes. -Includes two main exceptions: :class:`.RedditAPIException` for when something -goes wrong on the server side, and :class:`.ClientException` when something -goes wrong on the client side. Both of these classes extend -:class:`.AsyncPRAWException`. +Includes two main exceptions: :class:`.RedditAPIException` for when something goes wrong +on the server side, and :class:`.ClientException` when something goes wrong on the +client side. Both of these classes extend :class:`.AsyncPRAWException`. All other exceptions are subclassed from :class:`.ClientException`. @@ -37,6 +36,7 @@ def __init__(self, error_type: str, message: str, field: Optional[str] = None): :param error_type: The error type set on Reddit's end. :param message: The associated message for the error. :param field: The input field associated with the error, if available. + """ self.error_type = error_type self.message = message @@ -71,6 +71,7 @@ class APIException(AsyncPRAWException): Class :class:`.APIException` has been deprecated in favor of :class:`.RedditAPIException`. This class will be removed in Async PRAW 8.0. + """ @staticmethod @@ -93,11 +94,10 @@ def error_type(self) -> str: .. deprecated:: 7.0 - Accessing attributes through instances of - :class:`.RedditAPIException` is deprecated. This behavior will be - removed in Async PRAW 8.0. Check out the - :ref:`PRAW 7 Migration tutorial ` on how to - migrate code from this behavior. + Accessing attributes through instances of :class:`.RedditAPIException` is + deprecated. This behavior will be removed in Async PRAW 8.0. Check out the + :ref:`PRAW 7 Migration tutorial ` on how to migrate code + from this behavior. """ return self._get_old_attr("error_type") @@ -108,9 +108,8 @@ def message(self) -> str: .. deprecated:: 7.0 - Accessing attributes through instances of - :class:`.RedditAPIException` is deprecated. This behavior will be - removed in Async PRAW 8.0. Check out the + Accessing attributes through instances of :class:`.RedditAPIException` is + deprecated. This behavior will be removed in Async PRAW 8.0. Check out the :ref:`Async PRAW 7 Migration tutorial ` on how to migrate code from this behavior. @@ -123,11 +122,10 @@ def field(self) -> str: .. deprecated:: 7.0 - Accessing attributes through instances of - :class:`.RedditAPIException` is deprecated. This behavior will be - removed in Async PRAW 8.0. Check out the - :ref:`PRAW 7 Migration tutorial ` on how to - migrate code from this behavior. + Accessing attributes through instances of :class:`.RedditAPIException` is + deprecated. This behavior will be removed in Async PRAW 8.0. Check out the + :ref:`PRAW 7 Migration tutorial ` on how to migrate code + from this behavior. """ return self._get_old_attr("field") @@ -150,10 +148,11 @@ def __init__( ): """Initialize an instance of RedditAPIException. - :param items: Either a list of instances of :class:`.RedditErrorItem` - or a list containing lists of unformed errors. + :param items: Either a list of instances of :class:`.RedditErrorItem` or a list + containing lists of unformed errors. :param optional_args: Takes the second and third arguments that :class:`.APIException` used to take. + """ if isinstance(items, str): items = [[items, *optional_args]] @@ -208,8 +207,9 @@ def __init__(self, url: str, message: str = "Invalid URL: {}"): """Initialize the class. :param url: The invalid URL. - :param message: The message to display. Must contain a format - identifier (``{}`` or ``{0}``). (default: ``"Invalid URL: {}"``) + :param message: The message to display. Must contain a format identifier (``{}`` + or ``{0}``). (default: ``"Invalid URL: {}"``) + """ super().__init__(message.format(url)) @@ -230,6 +230,7 @@ def __init__(self, maximum_size: int, actual: int): :param maximum_size: The maximum_size size of the uploaded media. :param actual: The actual size of the uploaded media. + """ self.maximum_size = maximum_size self.actual = actual @@ -268,8 +269,10 @@ def __init__(self, message: str, exception: Optional[Exception]): :param message: The exception message. :param exception: The exception thrown by the websocket library. - .. note:: This parameter is deprecated. It will be removed in Async PRAW - 8.0. + .. note:: + + This parameter is deprecated. It will be removed in Async PRAW 8.0. + """ super().__init__(message) self._original_exception = exception diff --git a/asyncpraw/models/auth.py b/asyncpraw/models/auth.py index a9d96a517..ab259cc73 100644 --- a/asyncpraw/models/auth.py +++ b/asyncpraw/models/auth.py @@ -21,20 +21,19 @@ def limits(self) -> Dict[str, Optional[Union[str, int]]]: The keys are: - :remaining: The number of requests remaining to be made in the - current rate limit window. - :reset_timestamp: A unix timestamp providing an upper bound on when the - rate limit counters will reset. - :used: The number of requests made in the current rate limit - window. + :remaining: The number of requests remaining to be made in the current rate + limit window. + :reset_timestamp: A unix timestamp providing an upper bound on when the rate + limit counters will reset. + :used: The number of requests made in the current rate limit window. - All values are initially ``None`` as these values are set in response - to issued requests. + All values are initially ``None`` as these values are set in response to issued + requests. - The ``reset_timestamp`` value is an upper bound as the real timestamp - is computed on Reddit's end in preparation for sending the - response. This value may change slightly within a given window due to - slight changes in response times and rounding. + The ``reset_timestamp`` value is an upper bound as the real timestamp is + computed on Reddit's end in preparation for sending the response. This value may + change slightly within a given window due to slight changes in response times + and rounding. """ data = self._reddit._core._rate_limiter @@ -48,6 +47,7 @@ async def authorize(self, code: str) -> Optional[str]: """Complete the web authorization flow and return the refresh token. :param code: The code obtained through the request to the redirect uri. + :returns: The obtained refresh token, if available, otherwise ``None``. The session's active authorization will be updated upon success. @@ -64,16 +64,16 @@ def implicit(self, access_token: str, expires_in: int, scope: str) -> None: """Set the active authorization to be an implicit authorization. :param access_token: The access_token obtained from Reddit's callback. - :param expires_in: The number of seconds the ``access_token`` is valid - for. The origin of this value was returned from Reddit's callback. - You may need to subtract an offset before passing in this number to - account for a delay between when Reddit prepared the response, and - when you make this function call. - :param scope: A space-delimited string of Reddit OAuth2 scope names as - returned from Reddit's callback. + :param expires_in: The number of seconds the ``access_token`` is valid for. The + origin of this value was returned from Reddit's callback. You may need to + subtract an offset before passing in this number to account for a delay + between when Reddit prepared the response, and when you make this function + call. + :param scope: A space-delimited string of Reddit OAuth2 scope names as returned + from Reddit's callback. - :raises: :class:`.InvalidImplicitAuth` if :class:`.Reddit` was - initialized for a non-installed application type. + :raises: :class:`.InvalidImplicitAuth` if :class:`.Reddit` was initialized for a + non-installed application type. """ authenticator = self._reddit._read_only_core._authorizer._authenticator @@ -106,18 +106,17 @@ def url( :param scopes: A list of OAuth scopes to request authorization for. :param state: A string that will be reflected in the callback to - ``redirect_uri``. This value should be temporarily unique to the - client for whom the URL was generated for. - :param duration: Either ``permanent`` or ``temporary`` (default: - permanent). ``temporary`` authorizations generate access tokens - that last only 1 hour. ``permanent`` authorizations additionally - ``permanent`` authorizations additionally generate a single-use refresh - token with a significantly longer expiration (~1 year) that is to be used to - fetch a new set of tokens. This value is ignored when ``implicit=True``. - :param implicit: For **installed** applications, this value can be set - to use the implicit, rather than the code flow. When True, the - ``duration`` argument has no effect as only temporary tokens can be - retrieved. + ``redirect_uri``. This value should be temporarily unique to the client for + whom the URL was generated for. + :param duration: Either ``permanent`` or ``temporary`` (default: permanent). + ``temporary`` authorizations generate access tokens that last only 1 hour. + ``permanent`` authorizations additionally ``permanent`` authorizations + additionally generate a single-use refresh token with a significantly longer + expiration (~1 year) that is to be used to fetch a new set of tokens. This + value is ignored when ``implicit=True``. + :param implicit: For **installed** applications, this value can be set to use + the implicit, rather than the code flow. When True, the ``duration`` + argument has no effect as only temporary tokens can be retrieved. .. note:: diff --git a/asyncpraw/models/base.py b/asyncpraw/models/base.py index b4fc91435..402862df7 100644 --- a/asyncpraw/models/base.py +++ b/asyncpraw/models/base.py @@ -13,10 +13,9 @@ class AsyncPRAWBase: def _safely_add_arguments(argument_dict, key, **new_arguments): """Replace argument_dict[key] with a deepcopy and update. - This method is often called when new parameters need to be added to a - request. By calling this method and adding the new or updated - parameters we can insure we don't modify the dictionary passed in by - the caller. + This method is often called when new parameters need to be added to a request. + By calling this method and adding the new or updated parameters we can insure we + don't modify the dictionary passed in by the caller. """ value = deepcopy(argument_dict[key]) if key in argument_dict else {} diff --git a/asyncpraw/models/comment_forest.py b/asyncpraw/models/comment_forest.py index 3aa222946..6669671fb 100644 --- a/asyncpraw/models/comment_forest.py +++ b/asyncpraw/models/comment_forest.py @@ -44,8 +44,8 @@ def __getitem__(self, index: int): comments = await submission.comments() first_comment = comments[0] - Alternatively, the presence of this method enables one to iterate over - all top level comments, like so: + Alternatively, the presence of this method enables one to iterate over all top + level comments, like so: .. code-block:: python @@ -78,10 +78,9 @@ def __init__( ): """Initialize a CommentForest instance. - :param submission: An instance of :class:`~.Subreddit` that is the - parent of the comments. - :param comments: Initialize the Forest with a list of comments - (default: None). + :param submission: An instance of :class:`~.Subreddit` that is the parent of the + comments. + :param comments: Initialize the Forest with a list of comments (default: None). """ self._comments = comments @@ -118,8 +117,8 @@ async def list( ) -> List[Union["asyncpraw.models.Comment", "asyncpraw.models.MoreComments"]]: """Return a flattened list of all Comments. - This list may contain :class:`.MoreComments` instances if - :meth:`.replace_more` was not called first. + This list may contain :class:`.MoreComments` instances if :meth:`.replace_more` + was not called first. """ comments = [] @@ -136,18 +135,16 @@ async def replace_more( ) -> List["asyncpraw.models.MoreComments"]: """Update the comment forest by resolving instances of MoreComments. - :param limit: The maximum number of :class:`.MoreComments` instances to - replace. Each replacement requires 1 API request. Set to ``None`` - to have no limit, or to ``0`` to remove all :class:`.MoreComments` - instances without additional requests (default: 32). + :param limit: The maximum number of :class:`.MoreComments` instances to replace. + Each replacement requires 1 API request. Set to ``None`` to have no limit, + or to ``0`` to remove all :class:`.MoreComments` instances without + additional requests (default: 32). :param threshold: The minimum number of children comments a - :class:`.MoreComments` instance must have in order to be - replaced. :class:`.MoreComments` instances that represent "continue - this thread" links unfortunately appear to have 0 - children. (default: 0). + :class:`.MoreComments` instance must have in order to be replaced. + :class:`.MoreComments` instances that represent "continue this thread" links + unfortunately appear to have 0 children. (default: 0). - :returns: A list of :class:`.MoreComments` instances that were not - replaced. + :returns: A list of :class:`.MoreComments` instances that were not replaced. For example, to replace up to 32 :class:`.MoreComments` instances of a submission try: @@ -158,34 +155,36 @@ async def replace_more( comments = await submission.comments() await comments.replace_more() - Alternatively, to replace :class:`.MoreComments` instances within the - replies of a single comment try: + Alternatively, to replace :class:`.MoreComments` instances within the replies of + a single comment try: .. code-block:: python comment = await reddit.comment("d8r4im1") await comment.replies.replace_more() - .. note:: This method can take a long time as each replacement will - discover at most 20 new :class:`.Comment` or - :class:`.MoreComments` instances. As a result, consider - looping and handling exceptions until the method returns - successfully. For example: - - .. code-block:: python - - while True: - try: - comments = await submission.comments() - await comments.replace_more() - break - except PossibleExceptions: - print("Handling replace_more exception") - await asyncio.sleep(1) - - .. warning:: If this method is called, and the comments are refreshed, - calling this method again will result in a - :class:`.DuplicateReplaceException`. + .. note:: + + This method can take a long time as each replacement will discover at most + 20 new :class:`.Comment` or :class:`.MoreComments` instances. As a result, + consider looping and handling exceptions until the method returns + successfully. For example: + + .. code-block:: python + + while True: + try: + comments = await submission.comments() + await comments.replace_more() + break + except PossibleExceptions: + print("Handling replace_more exception") + await asyncio.sleep(1) + + .. warning:: + + If this method is called, and the comments are refreshed, calling this + method again will result in a :class:`.DuplicateReplaceException`. """ remaining = limit diff --git a/asyncpraw/models/helpers.py b/asyncpraw/models/helpers.py index c09930622..dd863dca3 100644 --- a/asyncpraw/models/helpers.py +++ b/asyncpraw/models/helpers.py @@ -25,7 +25,8 @@ async def __call__( livethread = await reddit.live("ukaeu1ik4sw5") - If you need the object fetched right away (e.g., to access attributes) you can do: + If you need the object fetched right away (e.g., to access attributes) you can + do: .. code-block:: python @@ -34,6 +35,7 @@ async def __call__( :param id: A live thread ID, e.g., ``ukaeu1ik4sw5``. :param fetch: Determines if the object is lazily loaded (default: False). + """ live_thread = LiveThread(self._reddit, id=id) if fetch: @@ -46,6 +48,7 @@ def info( """Fetch information about each live thread in ``ids``. :param ids: A list of IDs for a live thread. + :returns: A generator that yields :class:`.LiveThread` instances. :raises: ``asyncprawcore.ServerError`` if invalid live threads are requested. @@ -53,19 +56,19 @@ def info( Requests will be issued in batches for each 100 IDs. .. note:: + This method doesn't support IDs for live updates. .. warning:: - Unlike :meth:`.Reddit.info`, the output of this method - may not reflect the order of input. + + Unlike :meth:`.Reddit.info`, the output of this method may not reflect the + order of input. Usage: .. code-block:: python - ids = ["3rgnbke2rai6hen7ciytwcxadi", - "sw7bubeycai6hey4ciytwamw3a", - "t8jnufucss07"] + ids = ["3rgnbke2rai6hen7ciytwcxadi", "sw7bubeycai6hey4ciytwamw3a", "t8jnufucss07"] async for thread in reddit.live.info(ids): print(thread.title) @@ -94,10 +97,11 @@ async def create( :param title: The title of the new LiveThread. :param description: (Optional) The new LiveThread's description. - :param nsfw: (boolean) Indicate whether this thread is not safe for - work (default: False). - :param resources: (Optional) Markdown formatted information that is - useful for the LiveThread. + :param nsfw: (boolean) Indicate whether this thread is not safe for work + (default: False). + :param resources: (Optional) Markdown formatted information that is useful for + the LiveThread. + :returns: The new LiveThread object. """ @@ -114,8 +118,8 @@ async def create( async def now(self) -> Optional["asyncpraw.models.LiveThread"]: """Get the currently featured live thread. - :returns: The :class:`.LiveThread` object, or ``None`` if there is - no currently featured live thread. + :returns: The :class:`.LiveThread` object, or ``None`` if there is no currently + featured live thread. Usage: @@ -138,7 +142,8 @@ async def __call__( ) -> "asyncpraw.models.Multireddit": """Return an instance of :class:`~.Multireddit`. - If you need the object fetched right away (e.g., to access an attribute) you can do: + If you need the object fetched right away (e.g., to access an attribute) you can + do: .. code-block:: python @@ -146,10 +151,11 @@ async def __call__( async for comment in multireddit.comments(limit=25): print(comment.author) - :param redditor: A redditor name (e.g., ``"spez"``) or - :class:`~.Redditor` instance who owns the multireddit. + :param redditor: A redditor name (e.g., ``"spez"``) or :class:`~.Redditor` + instance who owns the multireddit. :param name: The name of the multireddit. :param fetch: Determines if the object is lazily loaded (default: False). + """ path = f"/user/{redditor}/m/{name}" multireddit = Multireddit(self._reddit, _data={"name": name, "path": path}) @@ -171,22 +177,21 @@ async def create( :param display_name: The display name for the new multireddit. :param subreddits: Subreddits to add to the new multireddit. - :param description_md: (Optional) Description for the new multireddit, - formatted in markdown. - :param icon_name: (Optional) Can be one of: ``art - and design``, ``ask``, ``books``, ``business``, ``cars``, - ``comics``, ``cute animals``, ``diy``, ``entertainment``, ``food - and drink``, ``funny``, ``games``, ``grooming``, ``health``, ``life - advice``, ``military``, ``models pinup``, ``music``, ``news``, - ``philosophy``, ``pictures and gifs``, ``science``, ``shopping``, - ``sports``, ``style``, ``tech``, ``travel``, ``unusual stories``, - ``video``, or ``None``. - :param key_color: (Optional) RGB hex color code of the form - ``"#FFFFFF"``. - :param visibility: (Optional) Can be one of: ``hidden``, ``private``, - ``public`` (default: private). - :param weighting_scheme: (Optional) Can be one of: ``classic``, - ``fresh`` (default: classic). + :param description_md: (Optional) Description for the new multireddit, formatted + in markdown. + :param icon_name: (Optional) Can be one of: ``art and design``, ``ask``, + ``books``, ``business``, ``cars``, ``comics``, ``cute animals``, ``diy``, + ``entertainment``, ``food and drink``, ``funny``, ``games``, ``grooming``, + ``health``, ``life advice``, ``military``, ``models pinup``, ``music``, + ``news``, ``philosophy``, ``pictures and gifs``, ``science``, ``shopping``, + ``sports``, ``style``, ``tech``, ``travel``, ``unusual stories``, ``video``, + or ``None``. + :param key_color: (Optional) RGB hex color code of the form ``"#FFFFFF"``. + :param visibility: (Optional) Can be one of: ``hidden``, ``private``, ``public`` + (default: private). + :param weighting_scheme: (Optional) Can be one of: ``classic``, ``fresh`` + (default: classic). + :returns: The new Multireddit object. """ @@ -212,7 +217,8 @@ async def __call__( ) -> "asyncpraw.models.Subreddit": """Return an instance of :class:`~.Subreddit`. - If you need the object fetched right away (e.g., to access an attribute) you can do: + If you need the object fetched right away (e.g., to access an attribute) you can + do: .. code-block:: python @@ -222,6 +228,7 @@ async def __call__( :param display_name: The name of the subreddit. :param fetch: Determines if the object is lazily loaded (default: False). + """ lower_name = display_name.lower() @@ -246,24 +253,22 @@ async def create( """Create a new subreddit. :param name: The name for the new subreddit. - - :param title: The title of the subreddit. When ``None`` or ``""`` use - the value of ``name``. - - :param link_type: The types of submissions users can make. - One of ``any``, ``link``, ``self`` (default: any). - :param subreddit_type: One of ``archived``, ``employees_only``, - ``gold_only``, ``gold_restricted``, ``private``, ``public``, - ``restricted`` (default: public). - :param wikimode: One of ``anyone``, ``disabled``, ``modonly``. - - Any keyword parameters not provided, or set explicitly to None, will - take on a default value assigned by the Reddit server. + :param title: The title of the subreddit. When ``None`` or ``""`` use the value + of ``name``. + :param link_type: The types of submissions users can make. One of ``any``, + ``link``, ``self`` (default: any). + :param subreddit_type: One of ``archived``, ``employees_only``, ``gold_only``, + ``gold_restricted``, ``private``, ``public``, ``restricted`` (default: + public). + :param wikimode: One of ``anyone``, ``disabled``, ``modonly``. + + Any keyword parameters not provided, or set explicitly to None, will take on a + default value assigned by the Reddit server. .. seealso:: - :meth:`~.SubredditModeration.update` for documentation - of other available settings. + :meth:`~.SubredditModeration.update` for documentation of other available + settings. """ await Subreddit._create_or_update( diff --git a/asyncpraw/models/inbox.py b/asyncpraw/models/inbox.py index 42229d8b2..73d966b23 100644 --- a/asyncpraw/models/inbox.py +++ b/asyncpraw/models/inbox.py @@ -43,6 +43,7 @@ async def collapse(self, items: List["asyncpraw.models.Message"]): .. code-block:: python from asyncpraw.models import Message + unread_messages = [] async for item in reddit.inbox.unread(limit=None): if isinstance(item, Message): @@ -51,7 +52,7 @@ async def collapse(self, items: List["asyncpraw.models.Message"]): .. seealso:: - :meth:`.Message.uncollapse` + :meth:`.Message.uncollapse` """ while items: @@ -85,8 +86,8 @@ async def mark_read( """Mark Comments or Messages as read. :param items: A list containing instances of :class:`.Comment` and/or - :class:`.Message` to be be marked as read relative to the - authorized user's inbox. + :class:`.Message` to be be marked as read relative to the authorized user's + inbox. Requests are batched at 25 items (reddit limit). @@ -95,6 +96,7 @@ async def mark_read( .. code-block:: python from asyncpraw.models import Message + unread_messages = [] async for item in reddit.inbox.unread(limit=None): if isinstance(item, Message): @@ -103,7 +105,7 @@ async def mark_read( .. seealso:: - :meth:`.Comment.mark_read` and :meth:`.Message.mark_read` + :meth:`.Comment.mark_read` and :meth:`.Message.mark_read` """ while items: @@ -117,8 +119,8 @@ async def mark_unread( """Unmark Comments or Messages as read. :param items: A list containing instances of :class:`.Comment` and/or - :class:`.Message` to be be marked as unread relative to the - authorized user's inbox. + :class:`.Message` to be be marked as unread relative to the authorized + user's inbox. Requests are batched at 25 items (reddit limit). @@ -131,7 +133,7 @@ async def mark_unread( .. seealso:: - :meth:`.Comment.mark_unread` and :meth:`.Message.mark_unread` + :meth:`.Comment.mark_unread` and :meth:`.Message.mark_unread` """ while items: @@ -144,14 +146,13 @@ def mentions( ) -> AsyncIterator["asyncpraw.models.Comment"]: r"""Return a :class:`.ListingGenerator` for mentions. - A mention is :class:`.Comment` in which the authorized redditor is - named in its body like ``u/redditor_name``. + A mention is :class:`.Comment` in which the authorized redditor is named in its + body like ``u/redditor_name``. Additional keyword arguments are passed in the initialization of :class:`.ListingGenerator`. - For example, to output the author and body of the first 25 mentions - try: + For example, to output the author and body of the first 25 mentions try: .. code-block:: python @@ -206,8 +207,7 @@ def sent( Additional keyword arguments are passed in the initialization of :class:`.ListingGenerator`. - For example, to output the recipient of the most recent 15 messages - try: + For example, to output the recipient of the most recent 15 messages try: .. code-block:: python @@ -222,8 +222,8 @@ def stream( ) -> AsyncIterator[Union["asyncpraw.models.Comment", "asyncpraw.models.Message"]]: """Yield new inbox items as they become available. - Items are yielded oldest first. Up to 100 historical items will - initially be returned. + Items are yielded oldest first. Up to 100 historical items will initially be + returned. Keyword arguments are passed to :func:`.stream_generator`. @@ -269,6 +269,7 @@ async def uncollapse(self, items: List["asyncpraw.models.Message"]): .. code-block:: python from asyncpraw.models import Message + unread_messages = [] async for item in reddit.inbox.unread(limit=None): if isinstance(item, Message): @@ -277,7 +278,7 @@ async def uncollapse(self, items: List["asyncpraw.models.Message"]): .. seealso:: - :meth:`.Message.collapse` + :meth:`.Message.collapse` """ while items: @@ -294,8 +295,10 @@ def unread( :param mark_read: Marks the inbox as read (default: False). - .. note:: This only marks the inbox as read not the messages. Use - :meth:`.Inbox.mark_read` to mark the messages. + .. note:: + + This only marks the inbox as read not the messages. Use + :meth:`.Inbox.mark_read` to mark the messages. Additional keyword arguments are passed in the initialization of :class:`.ListingGenerator`. @@ -305,6 +308,7 @@ def unread( .. code-block:: python from asyncpraw.models import Comment + async for item in reddit.inbox.unread(limit=None): if isinstance(item, Comment): print(item.author) diff --git a/asyncpraw/models/list/trophy.py b/asyncpraw/models/list/trophy.py index eb3a6f405..6da53d9f9 100644 --- a/asyncpraw/models/list/trophy.py +++ b/asyncpraw/models/list/trophy.py @@ -5,8 +5,8 @@ class TrophyList(BaseList): """A list of trophies. - This class is solely used to parse responses from reddit, - so end users should not use this class directly. + This class is solely used to parse responses from reddit, so end users should not + use this class directly. """ diff --git a/asyncpraw/models/listing/generator.py b/asyncpraw/models/listing/generator.py index b41556fff..bc6f3626a 100644 --- a/asyncpraw/models/listing/generator.py +++ b/asyncpraw/models/listing/generator.py @@ -12,10 +12,12 @@ class ListingGenerator(AsyncPRAWBase, AsyncIterator): """Instances of this class generate :class:`.RedditBase` instances. - .. warning:: This class should not be directly utilized. Instead you will - find a number of methods that return instances of the class: + .. warning:: - http://asyncpraw.readthedocs.io/en/latest/search.html?q=ListingGenerator + This class should not be directly utilized. Instead you will find a number of + methods that return instances of the class: + + http://asyncpraw.readthedocs.io/en/latest/search.html?q=ListingGenerator """ @@ -30,13 +32,12 @@ def __init__( :param reddit: An instance of :class:`.Reddit`. :param url: A URL returning a reddit listing. - :param limit: The number of content entries to fetch. If ``limit`` is - None, then fetch as many entries as possible. Most of reddit's - listings contain a maximum of 1000 items, and are returned 100 at a - time. This class will automatically issue all necessary - requests (default: 100). - :param params: A dictionary containing additional query string - parameters to send with the request. + :param limit: The number of content entries to fetch. If ``limit`` is None, then + fetch as many entries as possible. Most of reddit's listings contain a + maximum of 1000 items, and are returned 100 at a time. This class will + automatically issue all necessary requests (default: 100). + :param params: A dictionary containing additional query string parameters to + send with the request. """ super().__init__(reddit, _data=None) diff --git a/asyncpraw/models/listing/mixins/base.py b/asyncpraw/models/listing/mixins/base.py index 45bf2d070..4e9fcfe52 100644 --- a/asyncpraw/models/listing/mixins/base.py +++ b/asyncpraw/models/listing/mixins/base.py @@ -37,8 +37,8 @@ def controversial( ) -> AsyncIterator[Any]: """Return a :class:`.ListingGenerator` for controversial submissions. - :param time_filter: Can be one of: all, day, hour, month, week, year - (default: all). + :param time_filter: Can be one of: all, day, hour, month, week, year (default: + all). :raises: :py:class:`.ValueError` if ``time_filter`` is invalid. @@ -49,22 +49,22 @@ def controversial( .. code-block:: python - reddit.domain("imgur.com").controversial("week") + reddit.domain("imgur.com").controversial("week") - multireddit = await reddit.multireddit("samuraisam", "programming") - multireddit.controversial("day") + multireddit = await reddit.multireddit("samuraisam", "programming") + multireddit.controversial("day") - redditor = await reddit.redditor("spez") - redditor.controversial("month") + redditor = await reddit.redditor("spez") + redditor.controversial("month") - redditor = await reddit.redditor("spez") - redditor.comments.controversial("year") + redditor = await reddit.redditor("spez") + redditor.comments.controversial("year") - redditor = await reddit.redditor("spez") - redditor.submissions.controversial("all") + redditor = await reddit.redditor("spez") + redditor.submissions.controversial("all") - subreddit = await reddit.subreddit("all") - subreddit.controversial("hour") + subreddit = await reddit.subreddit("all") + subreddit.controversial("hour") """ self._validate_time_filter(time_filter) @@ -84,22 +84,22 @@ def hot( .. code-block:: python - reddit.domain("imgur.com").hot() + reddit.domain("imgur.com").hot() - multireddit = await reddit.multireddit("samuraisam", "programming") - multireddit.hot() + multireddit = await reddit.multireddit("samuraisam", "programming") + multireddit.hot() - redditor = await reddit.redditor("spez") - redditor.hot() + redditor = await reddit.redditor("spez") + redditor.hot() - redditor = await reddit.redditor("spez") - redditor.comments.hot() + redditor = await reddit.redditor("spez") + redditor.comments.hot() - redditor = await reddit.redditor("spez") - redditor.submissions.hot() + redditor = await reddit.redditor("spez") + redditor.submissions.hot() - subreddit = await reddit.subreddit("all") - subreddit.hot() + subreddit = await reddit.subreddit("all") + subreddit.hot() """ generator_kwargs.setdefault("params", {}) @@ -118,22 +118,22 @@ def new( .. code-block:: python - reddit.domain("imgur.com").new() + reddit.domain("imgur.com").new() - multireddit = await reddit.multireddit("samuraisam", "programming") - multireddit.new() + multireddit = await reddit.multireddit("samuraisam", "programming") + multireddit.new() - redditor = await reddit.redditor("spez") - redditor.new() + redditor = await reddit.redditor("spez") + redditor.new() - redditor = await reddit.redditor("spez") - redditor.comments.new() + redditor = await reddit.redditor("spez") + redditor.comments.new() - redditor = await reddit.redditor("spez") - redditor.submissions.new() + redditor = await reddit.redditor("spez") + redditor.submissions.new() - subreddit = await reddit.subreddit("all") - subreddit.new() + subreddit = await reddit.subreddit("all") + subreddit.new() """ generator_kwargs.setdefault("params", {}) @@ -147,8 +147,8 @@ def top( ) -> AsyncIterator[Any]: """Return a :class:`.ListingGenerator` for top submissions. - :param time_filter: Can be one of: all, day, hour, month, week, year - (default: all). + :param time_filter: Can be one of: all, day, hour, month, week, year (default: + all). :raises: :py:class:`.ValueError` if ``time_filter`` is invalid. @@ -159,22 +159,22 @@ def top( .. code-block:: python - reddit.domain("imgur.com").top("week") + reddit.domain("imgur.com").top("week") - multireddit = await reddit.multireddit("samuraisam", "programming") - multireddit.top("day") + multireddit = await reddit.multireddit("samuraisam", "programming") + multireddit.top("day") - redditor = await reddit.redditor("spez") - redditor.top("month") + redditor = await reddit.redditor("spez") + redditor.top("month") - redditor = await reddit.redditor("spez") - redditor.comments.top("year") + redditor = await reddit.redditor("spez") + redditor.comments.top("year") - redditor = await reddit.redditor("spez") - redditor.submissions.top("all") + redditor = await reddit.redditor("spez") + redditor.submissions.top("all") - subreddit = await reddit.subreddit("all") - subreddit.top("hour") + subreddit = await reddit.subreddit("all") + subreddit.top("hour") """ self._validate_time_filter(time_filter) diff --git a/asyncpraw/models/listing/mixins/redditor.py b/asyncpraw/models/listing/mixins/redditor.py index ce26cbcdf..5826f699f 100644 --- a/asyncpraw/models/listing/mixins/redditor.py +++ b/asyncpraw/models/listing/mixins/redditor.py @@ -35,8 +35,7 @@ class RedditorListingMixin(BaseListingMixin, GildedListingMixin): def comments(self) -> SubListing: r"""Provide an instance of :class:`.SubListing` for comment access. - For example, to output the first line of all new comments by - ``u/spez`` try: + For example, to output the first line of all new comments by ``u/spez`` try: .. code-block:: python @@ -51,8 +50,8 @@ def comments(self) -> SubListing: def submissions(self) -> SubListing: """Provide an instance of :class:`.SubListing` for submission access. - For example, to output the title's of top 100 of all time submissions - for ``u/spez`` try: + For example, to output the title's of top 100 of all time submissions for + ``u/spez`` try: .. code-block:: python @@ -76,6 +75,7 @@ def downvoted( Since this function returns a :class:`.ListingGenerator` the exception may not occur until sometime after this function has returned. + Additional keyword arguments are passed in the initialization of :class:`.ListingGenerator`. @@ -105,6 +105,7 @@ def gildings( Since this function returns a :class:`.ListingGenerator` the exception may not occur until sometime after this function has returned. + Additional keyword arguments are passed in the initialization of :class:`.ListingGenerator`. @@ -134,6 +135,7 @@ def hidden( Since this function returns a :class:`.ListingGenerator` the exception may not occur until sometime after this function has returned. + Additional keyword arguments are passed in the initialization of :class:`.ListingGenerator`. @@ -163,6 +165,7 @@ def saved( Since this function returns a :class:`.ListingGenerator` the exception may not occur until sometime after this function has returned. + Additional keyword arguments are passed in the initialization of :class:`.ListingGenerator`. @@ -192,6 +195,7 @@ def upvoted( Since this function returns a :class:`.ListingGenerator` the exception may not occur until sometime after this function has returned. + Additional keyword arguments are passed in the initialization of :class:`.ListingGenerator`. diff --git a/asyncpraw/models/listing/mixins/submission.py b/asyncpraw/models/listing/mixins/submission.py index d2a0d2e7a..24ac836ca 100644 --- a/asyncpraw/models/listing/mixins/submission.py +++ b/asyncpraw/models/listing/mixins/submission.py @@ -30,7 +30,9 @@ def duplicates( # process each duplicate ... - .. seealso:: :meth:`~.upvote` + .. seealso:: + + :meth:`~.upvote` """ url = API_PATH["duplicates"].format(submission_id=self.id) diff --git a/asyncpraw/models/preferences.py b/asyncpraw/models/preferences.py index e65a86d97..094dd0f81 100644 --- a/asyncpraw/models/preferences.py +++ b/asyncpraw/models/preferences.py @@ -11,23 +11,24 @@ class Preferences: """A class for Reddit preferences. - The Preferences class provides access to the Reddit preferences of the - currently authenticated user. + The Preferences class provides access to the Reddit preferences of the currently + authenticated user. + """ async def __call__(self) -> Dict[str, Union[bool, int, str]]: """Return the preference settings of the authenticated user as a dict. - This method is intended to be accessed as ``reddit.user.preferences()`` - like so: + This method is intended to be accessed as ``reddit.user.preferences()`` like so: .. code-block:: python preferences = await reddit.user.preferences() print(preferences["show_link_flair"]) - See https://www.reddit.com/dev/api#GET_api_v1_me_prefs for the list - of possible values. + See https://www.reddit.com/dev/api#GET_api_v1_me_prefs for the list of possible + values. + """ return await self._reddit.get(API_PATH["preferences"]) @@ -35,6 +36,7 @@ def __init__(self, reddit: "asyncpraw.Reddit"): """Create a Preferences instance. :param reddit: The Reddit instance. + """ self._reddit = reddit @@ -164,11 +166,11 @@ async def update(self, **preferences: Union[bool, int, str]): :param video_autoplay: Autoplay Reddit videos on the desktop comments page (boolean). - Additional keyword arguments can be provided to handle new settings as - Reddit introduces them. + Additional keyword arguments can be provided to handle new settings as Reddit + introduces them. - See https://www.reddit.com/dev/api#PATCH_api_v1_me_prefs for the - most up-to-date list of possible parameters. + See https://www.reddit.com/dev/api#PATCH_api_v1_me_prefs for the most up-to-date + list of possible parameters. This is intended to be used like so: @@ -176,9 +178,8 @@ async def update(self, **preferences: Union[bool, int, str]): await reddit.user.preferences.update(show_link_flair=True) - This method returns the new state of the - preferences as a ``dict``, which can be used to check whether a - change went through. + This method returns the new state of the preferences as a ``dict``, which can be + used to check whether a change went through. .. code-block:: python @@ -186,17 +187,17 @@ async def update(self, **preferences: Union[bool, int, str]): new_preferences = await original_preferences.update(invalid_param=123) print(original_preferences == new_preferences) # True, no change - .. warning:: Passing an unknown parameter name or an illegal value - (such as an int when a boolean is expected) does not - result in an error from the Reddit API. As a consequence, - any invalid input will fail silently. To verify that - changes have been made, use the return value of this - method, which is a dict of the preferences after the - update action has been performed. - - Some preferences have names that are not valid keyword arguments in - Python. To update these, construct a ``dict`` and use ``**`` to unpack - it as keyword arguments: + .. warning:: + + Passing an unknown parameter name or an illegal value (such as an int when a + boolean is expected) does not result in an error from the Reddit API. As a + consequence, any invalid input will fail silently. To verify that changes + have been made, use the return value of this method, which is a dict of the + preferences after the update action has been performed. + + Some preferences have names that are not valid keyword arguments in Python. To + update these, construct a ``dict`` and use ``**`` to unpack it as keyword + arguments: .. code-block:: python diff --git a/asyncpraw/models/reddit/base.py b/asyncpraw/models/reddit/base.py index fde0a7ae5..06bb312bb 100644 --- a/asyncpraw/models/reddit/base.py +++ b/asyncpraw/models/reddit/base.py @@ -109,5 +109,6 @@ async def load(self): .. code-block:: python await reddit_base_object.load() + """ await self._fetch() diff --git a/asyncpraw/models/reddit/collections.py b/asyncpraw/models/reddit/collections.py index 4638bdc0e..a0933bcf9 100644 --- a/asyncpraw/models/reddit/collections.py +++ b/asyncpraw/models/reddit/collections.py @@ -24,13 +24,16 @@ class CollectionModeration(AsyncPRAWBase): subreddit = await reddit.subreddit("SUBREDDIT") collection = await subreddit.collections("some_uuid") collection.mod + """ def _post_fullname(self, post): """Get a post's fullname. :param post: A fullname, a Submission, a permalink, or an ID. + :returns: The fullname of the post. + """ if isinstance(post, Submission): return post.fullname @@ -47,6 +50,7 @@ def __init__(self, reddit: "asyncpraw.Reddit", collection_id: str): """Initialize an instance of CollectionModeration. :param collection_id: The ID of a collection. + """ super().__init__(reddit, _data=None) self.collection_id = collection_id @@ -54,9 +58,8 @@ def __init__(self, reddit: "asyncpraw.Reddit", collection_id: str): async def add_post(self, submission: "asyncpraw.models.Submission"): """Add a post to the collection. - :param submission: The post to add, a :class:`.Submission`, its - permalink as a ``str``, its fullname as a ``str``, or its ID as a - ``str``. + :param submission: The post to add, a :class:`.Submission`, its permalink as a + ``str``, its fullname as a ``str``, or its ID as a ``str``. Example usage: @@ -66,7 +69,9 @@ async def add_post(self, submission: "asyncpraw.models.Submission"): collection = await subreddit.collections("some_uuid") await collection.mod.add_post("bgibu9") - .. seealso:: :meth:`.remove_post` + .. seealso:: + + :meth:`.remove_post` """ link_fullname = self._post_fullname(submission) @@ -87,7 +92,9 @@ async def delete(self): collection = await subreddit.collections("some_uuid") await collection.mod.delete() - .. seealso:: :meth:`~.SubredditCollectionsModeration.create` + .. seealso:: + + :meth:`~.SubredditCollectionsModeration.create` """ await self._reddit.post( @@ -98,9 +105,8 @@ async def delete(self): async def remove_post(self, submission: "asyncpraw.models.Submission"): """Remove a post from the collection. - :param submission: The post to remove, a :class:`.Submission`, its - permalink as a ``str``, its fullname as a ``str``, or its ID as a - ``str``. + :param submission: The post to remove, a :class:`.Submission`, its permalink as + a ``str``, its fullname as a ``str``, or its ID as a ``str``. Example usage: @@ -110,7 +116,9 @@ async def remove_post(self, submission: "asyncpraw.models.Submission"): collection = await subreddit.collections("some_uuid") await collection.mod.remove_post("bgibu9") - .. seealso:: :meth:`.add_post` + .. seealso:: + + :meth:`.add_post` """ link_fullname = self._post_fullname(submission) @@ -123,8 +131,8 @@ async def remove_post(self, submission: "asyncpraw.models.Submission"): async def reorder(self, links: List[Union[str, "asyncpraw.models.Submission"]]): """Reorder posts in the collection. - :param links: A ``list`` of submissions, as :class:`.Submission`, - permalink as a ``str``, fullname as a ``str``, or ID as a ``str``. + :param links: A ``list`` of submissions, as :class:`.Submission`, permalink as a + ``str``, fullname as a ``str``, or ID as a ``str``. Example usage: @@ -156,7 +164,9 @@ async def update_description(self, description: str): collection = await subreddit.collections("some_uuid") await collection.mod.update_description("Please enjoy these links") - .. seealso:: :meth:`.update_title` + .. seealso:: + + :meth:`.update_title` """ await self._reddit.post( @@ -177,7 +187,9 @@ async def update_title(self, title: str): collection = await subreddit.collections("some_uuid") await collection.mod.update_title("Titley McTitleface") - .. seealso:: :meth:`.update_description` + .. seealso:: + + :meth:`.update_description` """ await self._reddit.post( @@ -202,34 +214,33 @@ class Collection(RedditBase): subreddit = await reddit.subreddit("SUBREDDIT") collection = await subreddit.collections( - permalink="https://reddit.com/r/SUBREDDIT/collection/some_uuid") + permalink="https://reddit.com/r/SUBREDDIT/collection/some_uuid" + ) **Typical Attributes** - This table describes attributes that typically belong to objects of this - class. Since attributes are dynamically provided (see - :ref:`determine-available-attributes-of-an-object`), there is not a - guarantee that these attributes will always be present, nor that they - will be the only attributes present. - - ======================= ================================================== - Attribute Description - ======================= ================================================== - ``author`` The :class:`.Redditor` who created the collection. - ``collection_id`` The UUID of the collection. - ``created_at_utc`` Time the collection was created, represented in - `Unix Time`_. - ``description`` The collection description. - ``last_update_utc`` Time the collection was last updated, represented - in `Unix Time`_. - ``link_ids`` A ``list`` of :class:`.Submission` fullnames. - ``permalink`` The collection's permalink (to view on the web). - ``sorted_links`` An iterable listing of the posts in - this collection. - ``title`` The title of the collection. - ======================= ================================================== - - .. _Unix Time: https://en.wikipedia.org/wiki/Unix_time + This table describes attributes that typically belong to objects of this class. + Since attributes are dynamically provided (see + :ref:`determine-available-attributes-of-an-object`), there is not a guarantee that + these attributes will always be present, nor that they will be the only attributes + present. + + =================== ============================================================= + Attribute Description + =================== ============================================================= + ``author`` The :class:`.Redditor` who created the collection. + ``collection_id`` The UUID of the collection. + ``created_at_utc`` Time the collection was created, represented in `Unix Time`_. + ``description`` The collection description. + ``last_update_utc`` Time the collection was last updated, represented in `Unix + Time`_. + ``link_ids`` A ``list`` of :class:`.Submission` fullnames. + ``permalink`` The collection's permalink (to view on the web). + ``sorted_links`` An iterable listing of the posts in this collection. + ``title`` The title of the collection. + =================== ============================================================= + + .. _unix time: https://en.wikipedia.org/wiki/Unix_time """ @@ -242,8 +253,8 @@ def mod(self) -> CollectionModeration: Provides access to various methods, including :meth:`~reddit.collections.CollectionModeration.add_post`, :meth:`~reddit.collections.CollectionModeration.delete`, - :meth:`~reddit.collections.CollectionModeration.reorder`, - and :meth:`~reddit.collections.CollectionModeration.update_title`. + :meth:`~reddit.collections.CollectionModeration.reorder`, and + :meth:`~reddit.collections.CollectionModeration.update_title`. Example usage: @@ -284,6 +295,7 @@ def __init__( :param _data: Any data associated with the Collection (optional). :param collection_id: The ID of the Collection (optional). :param permalink: The permalink of the Collection (optional). + """ if (_data, collection_id, permalink).count(None) != 2: raise TypeError( @@ -377,7 +389,10 @@ async def follow(self): collection = await subreddit.collections("some_uuid") await collection.follow() - .. seealso:: :meth:`~.unfollow` + .. seealso:: + + :meth:`~.unfollow` + """ await self._reddit.post( API_PATH["collection_follow"], @@ -395,7 +410,10 @@ async def unfollow(self): collection = await subreddit.collections("some_uuid") await collection.unfollow() - .. seealso:: :meth:`~.follow` + .. seealso:: + + :meth:`~.follow` + """ await self._reddit.post( API_PATH["collection_follow"], @@ -428,8 +446,8 @@ def __init__( async def create(self, title: str, description: str): """Create a new :class:`.Collection`. - The authenticated account must have appropriate moderator - permissions in the subreddit this collection belongs to. + The authenticated account must have appropriate moderator permissions in the + subreddit this collection belongs to. :param title: The title of the collection, up to 300 characters. :param description: The description, up to 500 characters. @@ -444,7 +462,9 @@ async def create(self, title: str, description: str): new_collection = await sub.collections.mod.create("Title", "desc") await new_collection.mod.add_post("bgibu9") - .. seealso:: :meth:`~CollectionModeration.delete` + .. seealso:: + + :meth:`~CollectionModeration.delete` """ if not self.subreddit._fetched: @@ -496,6 +516,7 @@ async def __call__( :param collection_id: The ID of a Collection (default: None). :param permalink: The permalink of a Collection (default: None). :param lazy: If True, object is loaded lazily (default: False) + :returns: The specified Collection. Exactly one of ``collection_id`` and ``permalink`` is required. @@ -516,8 +537,8 @@ async def __call__( print(collection.title) print(collection.description) - If you don't need the object fetched right away (e.g., to utilize a - class method) you can do: + If you don't need the object fetched right away (e.g., to utilize a class + method) you can do: .. code-block:: python diff --git a/asyncpraw/models/reddit/comment.py b/asyncpraw/models/reddit/comment.py index 4794d3617..9c0a5a934 100644 --- a/asyncpraw/models/reddit/comment.py +++ b/asyncpraw/models/reddit/comment.py @@ -24,44 +24,41 @@ class Comment(InboxableMixin, UserContentMixin, FullnameMixin, RedditBase): **Typical Attributes** - This table describes attributes that typically belong to objects of this - class. Since attributes are dynamically provided (see - :ref:`determine-available-attributes-of-an-object`), there is not a - guarantee that these attributes will always be present, nor is this list - necessarily complete. - - ======================= =================================================== - Attribute Description - ======================= =================================================== - ``author`` Provides an instance of :class:`.Redditor`. - ``body`` The body of the comment, as Markdown. - ``body_html`` The body of the comment, as HTML. - ``created_utc`` Time the comment was created, represented in - `Unix Time`_. - ``distinguished`` Whether or not the comment is distinguished. - ``edited`` Whether or not the comment has been edited. - ``id`` The ID of the comment. - ``is_submitter`` Whether or not the comment author is also the - author of the submission. - ``link_id`` The submission ID that the comment belongs to. - ``parent_id`` The ID of the parent comment (prefixed with ``t1_``). - If it is a top-level comment, this returns the - submission ID instead (prefixed with ``t3_``). - ``permalink`` A permalink for the comment. Comment objects from - the inbox have a ``context`` attribute instead. - ``replies`` Provides an instance of :class:`.CommentForest`. - ``saved`` Whether or not the comment is saved. - ``score`` The number of upvotes for the comment. - ``stickied`` Whether or not the comment is stickied. - ``submission`` Provides an instance of :class:`.Submission`. The - submission that the comment belongs to. - ``subreddit`` Provides an instance of :class:`.Subreddit`. The - subreddit that the comment belongs to. - ``subreddit_id`` The subreddit ID that the comment belongs to. - ======================= =================================================== - - - .. _Unix Time: https://en.wikipedia.org/wiki/Unix_time + This table describes attributes that typically belong to objects of this class. + Since attributes are dynamically provided (see + :ref:`determine-available-attributes-of-an-object`), there is not a guarantee that + these attributes will always be present, nor is this list necessarily complete. + + ================= ================================================================== + Attribute Description + ================= ================================================================== + ``author`` Provides an instance of :class:`.Redditor`. + ``body`` The body of the comment, as Markdown. + ``body_html`` The body of the comment, as HTML. + ``created_utc`` Time the comment was created, represented in `Unix Time`_. + ``distinguished`` Whether or not the comment is distinguished. + ``edited`` Whether or not the comment has been edited. + ``id`` The ID of the comment. + ``is_submitter`` Whether or not the comment author is also the author of the + submission. + ``link_id`` The submission ID that the comment belongs to. + ``parent_id`` The ID of the parent comment (prefixed with ``t1_``). If it is a + top-level comment, this returns the submission ID instead + (prefixed with ``t3_``). + ``permalink`` A permalink for the comment. Comment objects from the inbox have a + ``context`` attribute instead. + ``replies`` Provides an instance of :class:`.CommentForest`. + ``saved`` Whether or not the comment is saved. + ``score`` The number of upvotes for the comment. + ``stickied`` Whether or not the comment is stickied. + ``submission`` Provides an instance of :class:`.Submission`. The submission that + the comment belongs to. + ``subreddit`` Provides an instance of :class:`.Subreddit`. The subreddit that + the comment belongs to. + ``subreddit_id`` The subreddit ID that the comment belongs to. + ================= ================================================================== + + .. _unix time: https://en.wikipedia.org/wiki/Unix_time """ @@ -114,22 +111,23 @@ def mod(self) -> "asyncpraw.models.reddit.comment.CommentModeration": def replies(self) -> CommentForest: """Provide an instance of :class:`.CommentForest`. - This property may return an empty list if the comment - has not been refreshed with :meth:`.refresh()` + This property may return an empty list if the comment has not been refreshed + with :meth:`.refresh()` Sort order and reply limit can be set with the ``reply_sort`` and - ``reply_limit`` attributes before replies are fetched, including - any call to :meth:`.refresh`: + ``reply_limit`` attributes before replies are fetched, including any call to + :meth:`.refresh`: .. code-block:: python - comment.reply_sort = "new" - await comment.refresh() - replies = comment.replies + comment.reply_sort = "new" + await comment.refresh() + replies = comment.replies - .. note:: The appropriate values for ``reply_sort`` include - ``confidence``, ``controversial``, ``new``, ``old``, ``q&a``, - and ``top``. + .. note:: + + The appropriate values for ``reply_sort`` include ``confidence``, + ``controversial``, ``new``, ``old``, ``q&a``, and ``top``. """ if isinstance(self._replies, list): @@ -230,15 +228,15 @@ async def parent( ) -> Union["Comment", "asyncpraw.models.Submission"]: """Return the parent of the comment. - The returned parent will be an instance of either - :class:`.Comment`, or :class:`.Submission`. + The returned parent will be an instance of either :class:`.Comment`, or + :class:`.Submission`. - If this comment was obtained through a :class:`.Submission`, then its - entire ancestry should be immediately available, requiring no extra - network requests. However, if this comment was obtained through other - means, e.g., ``await reddit.comment("COMMENT_ID")``, or - ``reddit.inbox.comment_replies``, then the returned parent may be an - instance of either :class:`.Comment`, or :class:`.Submission`. + If this comment was obtained through a :class:`.Submission`, then its entire + ancestry should be immediately available, requiring no extra network requests. + However, if this comment was obtained through other means, e.g., ``await + reddit.comment("COMMENT_ID")``, or ``reddit.inbox.comment_replies``, then the + returned parent may be an instance of either :class:`.Comment`, or + :class:`.Submission`. Lazy comment example: @@ -251,19 +249,20 @@ async def parent( await parent.refresh() print(parent.replies) # Output is at least: [Comment(id="cklhv0f")] - .. warning:: Successive calls to :meth:`.parent()` may result in a - network request per call when the comment is not obtained through a - :class:`.Submission`. See below for an example of how to minimize - requests. + .. warning:: + + Successive calls to :meth:`.parent()` may result in a network request per + call when the comment is not obtained through a :class:`.Submission`. See + below for an example of how to minimize requests. - If you have a deeply nested comment and wish to most efficiently - discover its top-most :class:`.Comment` ancestor you can chain - successive calls to :meth:`.parent()` with calls to :meth:`.refresh()` - at every 9 levels. For example: + If you have a deeply nested comment and wish to most efficiently discover its + top-most :class:`.Comment` ancestor you can chain successive calls to + :meth:`.parent()` with calls to :meth:`.refresh()` at every 9 levels. For + example: .. code-block:: python - ancestor = await reddit.comment("dkk4qjd") + ancestor = await reddit.comment("dkk4qjd") refresh_counter = 0 while not ancestor.is_root: ancestor = await ancestor.parent() @@ -272,9 +271,8 @@ async def parent( refresh_counter += 1 print(f"Top-most Ancestor: {ancestor}") - The above code should result in 5 network requests to Reddit. Without - the calls to :meth:`.refresh()` it would make at least 31 network - requests. + The above code should result in 5 network requests to Reddit. Without the calls + to :meth:`.refresh()` it would make at least 31 network requests. """ # pylint: disable=no-member @@ -304,8 +302,8 @@ async def refresh(self): .. code-block:: python - comment = await reddit.comment("dkk4qjd", lazy=True) - await comment.refresh() + comment = await reddit.comment("dkk4qjd", lazy=True) + await comment.refresh() """ if "context" in self.__dict__: # Using hasattr triggers a fetch @@ -354,8 +352,8 @@ class CommentModeration(ThingModerationMixin): .. code-block:: python - comment = await reddit.comment("dkk4qjd", lazy=True) - await comment.mod.approve() + comment = await reddit.comment("dkk4qjd", lazy=True) + await comment.mod.approve() """ @@ -376,9 +374,10 @@ async def show(self): .. code-block:: python - # Uncollapse a comment: - comment = await reddit.comment("dkk4qjd", lazy=True) - await comment.mod.show() + # Uncollapse a comment: + comment = await reddit.comment("dkk4qjd", lazy=True) + await comment.mod.show() + """ url = API_PATH["show_comment"] diff --git a/asyncpraw/models/reddit/emoji.py b/asyncpraw/models/reddit/emoji.py index 28e2f04da..eedacccfe 100644 --- a/asyncpraw/models/reddit/emoji.py +++ b/asyncpraw/models/reddit/emoji.py @@ -15,21 +15,20 @@ class Emoji(RedditBase): **Typical Attributes** - This table describes attributes that typically belong to objects of this - class. Since attributes are dynamically provided (see - :ref:`determine-available-attributes-of-an-object`), there is not a - guarantee that these attributes will always be present, nor is this list - necessarily comprehensive. - - ======================= =================================================== - Attribute Description - ======================= =================================================== - ``mod_flair_only`` Whether the emoji is restricted for mod use only. - ``name`` The name of the emoji. - ``post_flair_allowed`` Whether the emoji may appear in post flair. - ``url`` The URL of the emoji image. - ``user_flair_allowed`` Whether the emoji may appear in user flair. - ======================= =================================================== + This table describes attributes that typically belong to objects of this class. + Since attributes are dynamically provided (see + :ref:`determine-available-attributes-of-an-object`), there is not a guarantee that + these attributes will always be present, nor is this list necessarily comprehensive. + + ====================== ================================================= + Attribute Description + ====================== ================================================= + ``mod_flair_only`` Whether the emoji is restricted for mod use only. + ``name`` The name of the emoji. + ``post_flair_allowed`` Whether the emoji may appear in post flair. + ``url`` The URL of the emoji image. + ``user_flair_allowed`` Whether the emoji may appear in user flair. + ====================== ================================================= """ @@ -92,22 +91,20 @@ async def update( ): """Update the permissions of an emoji in this subreddit. - :param mod_flair_only: (boolean) Indicate whether the emoji is - restricted to mod use only. Respects pre-existing settings if not - provided. - :param post_flair_allowed: (boolean) Indicate whether the emoji may - appear in post flair. Respects pre-existing settings if not - provided. - :param user_flair_allowed: (boolean) Indicate whether the emoji may - appear in user flair. Respects pre-existing settings if not - provided. + :param mod_flair_only: (boolean) Indicate whether the emoji is restricted to mod + use only. Respects pre-existing settings if not provided. + :param post_flair_allowed: (boolean) Indicate whether the emoji may appear in + post flair. Respects pre-existing settings if not provided. + :param user_flair_allowed: (boolean) Indicate whether the emoji may appear in + user flair. Respects pre-existing settings if not provided. - .. note:: In order to retain pre-existing values for those that are not - explicitly passed, a network request is issued. To avoid that - network request, explicitly provide all values. + .. note:: - To restrict the emoji ``test`` in subreddit ``wowemoji`` to mod use - only, try: + In order to retain pre-existing values for those that are not explicitly + passed, a network request is issued. To avoid that network request, + explicitly provide all values. + + To restrict the emoji ``test`` in subreddit ``wowemoji`` to mod use only, try: .. code-block:: python @@ -156,9 +153,8 @@ async def get_emoji(self, name: str, lazy: bool = False) -> Emoji: emoji = await subreddit.emoji.get_emoji("test") print(emoji) - - If you don't need the object fetched right away (e.g., to utilize a - class method) you can do: + If you don't need the object fetched right away (e.g., to utilize a class + method) you can do: .. code-block:: python @@ -217,12 +213,13 @@ async def add( :param name: The name of the emoji :param image_path: A path to a jpeg or png image. - :param mod_flair_only: (boolean) When provided, indicate whether the - emoji is restricted to mod use only. (Default: ``None``) - :param post_flair_allowed: (boolean) When provided, indicate whether - the emoji may appear in post flair. (Default: ``None``) - :param user_flair_allowed: (boolean) When provided, indicate whether - the emoji may appear in user flair. (Default: ``None``) + :param mod_flair_only: (boolean) When provided, indicate whether the emoji is + restricted to mod use only. (Default: ``None``) + :param post_flair_allowed: (boolean) When provided, indicate whether the emoji + may appear in post flair. (Default: ``None``) + :param user_flair_allowed: (boolean) When provided, indicate whether the emoji + may appear in user flair. (Default: ``None``) + :returns: The Emoji added. To add ``test`` to the subreddit ``praw_test`` try: diff --git a/asyncpraw/models/reddit/live.py b/asyncpraw/models/reddit/live.py index 3cc085a7e..0eec74e79 100644 --- a/asyncpraw/models/reddit/live.py +++ b/asyncpraw/models/reddit/live.py @@ -35,6 +35,7 @@ def __call__(self) -> AsyncIterator["asyncpraw.models.Redditor"]: thread = await reddit.live("ukaeu1ik4sw5") async for contributor in thread.contributor(): print(contributor) + """ async def generator(): @@ -51,9 +52,11 @@ def __init__(self, thread: "asyncpraw.models.LiveThread"): :param thread: An instance of :class:`.LiveThread`. - .. note:: This class should not be initialized directly. Instead obtain - an instance via: ``thread.contributor`` where ``thread`` is a - :class:`.LiveThread` instance. + .. note:: + + This class should not be initialized directly. Instead obtain an instance + via: ``thread.contributor`` where ``thread`` is a :class:`.LiveThread` + instance. """ self.thread = thread @@ -79,15 +82,14 @@ async def invite( ): """Invite a redditor to be a contributor of the live thread. - :param redditor: A redditor name (e.g., ``"spez"``) or - :class:`~.Redditor` instance. - :param permissions: When provided (not ``None``), permissions should - be a list of strings specifying which subset of permissions to - grant. An empty list ``[]`` indicates no permissions, and when - not provided (``None``), indicates full permissions. + :param redditor: A redditor name (e.g., ``"spez"``) or :class:`~.Redditor` + instance. + :param permissions: When provided (not ``None``), permissions should be a list + of strings specifying which subset of permissions to grant. An empty list + ``[]`` indicates no permissions, and when not provided (``None``), indicates + full permissions. - :raises: :class:`.RedditAPIException` if the invitation - already exists. + :raises: :class:`.RedditAPIException` if the invitation already exists. Usage: @@ -99,8 +101,10 @@ async def invite( # "manage" and "settings" permissions await thread.contributor.invite(redditor, ["manage", "settings"]) - .. seealso:: :meth:`.LiveContributorRelationship.remove_invite` to - remove the invite for redditor. + .. seealso:: + + :meth:`.LiveContributorRelationship.remove_invite` to remove the invite for + redditor. """ url = API_PATH["live_invite"].format(id=self.thread.id) @@ -166,7 +170,8 @@ async def remove_invite(self, redditor: Union[str, "asyncpraw.models.Redditor"]) .. seealso:: - :meth:`.LiveContributorRelationship.invite` to invite a redditor to be a contributor of the live thread. + :meth:`.LiveContributorRelationship.invite` to invite a redditor to be a + contributor of the live thread. """ if isinstance(redditor, Redditor): @@ -184,13 +189,12 @@ async def update( ): """Update the contributor permissions for ``redditor``. - :param redditor: A redditor name (e.g., ``"spez"``) or - :class:`~.Redditor` instance. - :param permissions: When provided (not ``None``), permissions should - be a list of strings specifying which subset of permissions to - grant (other permissions are removed). An empty list ``[]`` - indicates no permissions, and when not provided (``None``), - indicates full permissions. + :param redditor: A redditor name (e.g., ``"spez"``) or :class:`~.Redditor` + instance. + :param permissions: When provided (not ``None``), permissions should be a list + of strings specifying which subset of permissions to grant (other + permissions are removed). An empty list ``[]`` indicates no permissions, and + when not provided (``None``), indicates full permissions. For example, to grant all permissions to the contributor, try: @@ -199,8 +203,8 @@ async def update( thread = await reddit.live("ukaeu1ik4sw5") await thread.contributor.update("spez") - To grant ``"access"`` and ``"edit"`` permissions (and to - remove other permissions), try: + To grant ``"access"`` and ``"edit"`` permissions (and to remove other + permissions), try: .. code-block:: python @@ -228,13 +232,12 @@ async def update_invite( ): """Update the contributor invite permissions for ``redditor``. - :param redditor: A redditor name (e.g., ``"spez"``) or - :class:`~.Redditor` instance. - :param permissions: When provided (not ``None``), permissions should - be a list of strings specifying which subset of permissions to - grant (other permissions are removed). An empty list ``[]`` - indicates no permissions, and when not provided (``None``), - indicates full permissions. + :param redditor: A redditor name (e.g., ``"spez"``) or :class:`~.Redditor` + instance. + :param permissions: When provided (not ``None``), permissions should be a list + of strings specifying which subset of permissions to grant (other + permissions are removed). An empty list ``[]`` indicates no permissions, and + when not provided (``None``), indicates full permissions. For example, to set all permissions to the invitation, try: @@ -243,8 +246,8 @@ async def update_invite( thread = await reddit.live("ukaeu1ik4sw5") await thread.contributor.update_invite("spez") - To set "access" and "edit" permissions (and to remove other - permissions) to the invitation, try: + To set "access" and "edit" permissions (and to remove other permissions) to the + invitation, try: .. code-block:: python @@ -271,25 +274,24 @@ class LiveThread(RedditBase): **Typical Attributes** - This table describes attributes that typically belong to objects of this - class. Since attributes are dynamically provided (see - :ref:`determine-available-attributes-of-an-object`), there is not a - guarantee that these attributes will always be present, nor is this list - necessarily complete. - - ======================= =================================================== - Attribute Description - ======================= =================================================== - ``created_utc`` The creation time of the live thread, in `Unix - Time`_. - ``description`` Description of the live thread, as Markdown. - ``description_html`` Description of the live thread, as HTML. - ``id`` The ID of the live thread. - ``nsfw`` A ``bool`` representing whether or not the live - thread is marked as NSFW. - ======================= =================================================== - - .. _Unix Time: https://en.wikipedia.org/wiki/Unix_time + This table describes attributes that typically belong to objects of this class. + Since attributes are dynamically provided (see + :ref:`determine-available-attributes-of-an-object`), there is not a guarantee that + these attributes will always be present, nor is this list necessarily complete. + + ==================== ========================================================= + Attribute Description + ==================== ========================================================= + ``created_utc`` The creation time of the live thread, in `Unix Time`_. + ``description`` Description of the live thread, as Markdown. + ``description_html`` Description of the live thread, as HTML. + ``id`` The ID of the live thread. + ``nsfw`` A ``bool`` representing whether or not the live thread is + marked as NSFW. + ==================== ========================================================= + + .. _unix time: https://en.wikipedia.org/wiki/Unix_time + """ STR_FIELD = "id" @@ -312,10 +314,9 @@ def contrib(self) -> "asyncpraw.models.reddit.live.LiveThreadContribution": def contributor(self) -> "asyncpraw.models.reddit.live.LiveContributorRelationship": """Provide an instance of :class:`.LiveContributorRelationship`. - You can call the instance to get a list of contributors which is - represented as :class:`.RedditorList` instance consists of - :class:`.Redditor` instances. Those Redditor instances have - ``permissions`` attributes as contributors: + You can call the instance to get a list of contributors which is represented as + :class:`.RedditorList` instance consists of :class:`.Redditor` instances. Those + Redditor instances have ``permissions`` attributes as contributors: .. code-block:: python @@ -331,18 +332,17 @@ def contributor(self) -> "asyncpraw.models.reddit.live.LiveContributorRelationsh def stream(self) -> "asyncpraw.models.reddit.live.LiveThreadStream": """Provide an instance of :class:`.LiveThreadStream`. - Streams are used to indefinitely retrieve new updates made to a - live thread, like: + Streams are used to indefinitely retrieve new updates made to a live thread, + like: .. code-block:: python for live_update in reddit.live("ta535s1hq2je").stream.updates(): print(live_update.body) - Updates are yielded oldest first as :class:`.LiveUpdate`. Up to 100 - historical updates will initially be returned. - To only retrieve new updates starting from when the stream is - created, pass ``skip_existing=True``: + Updates are yielded oldest first as :class:`.LiveUpdate`. Up to 100 historical + updates will initially be returned. To only retrieve new updates starting from + when the stream is created, pass ``skip_existing=True``: .. code-block:: python @@ -356,7 +356,10 @@ def stream(self) -> "asyncpraw.models.reddit.live.LiveThreadStream": def __eq__(self, other: Union[str, "asyncpraw.models.LiveThread"]) -> bool: """Return whether the other instance equals the current. - .. note:: This comparison is case sensitive. + .. note:: + + This comparison is case sensitive. + """ if isinstance(other, str): return other == str(self) @@ -367,7 +370,8 @@ async def get_update( ) -> "asyncpraw.models.LiveUpdate": """Return a :class:`.LiveUpdate` instance. - :param update_id: A live update ID, e.g., ``"7827987a-c998-11e4-a0b9-22000b6a88d2"``. + :param update_id: A live update ID, e.g., + ``"7827987a-c998-11e4-a0b9-22000b6a88d2"``. :param lazy: If True, object is loaded lazily (default: False). Usage: @@ -376,18 +380,19 @@ async def get_update( thread = await reddit.live("ukaeu1ik4sw5") update = await thread.get_update("7827987a-c998-11e4-a0b9-22000b6a88d2") - update.thread # LiveThread(id="ukaeu1ik4sw5") - update.id # "7827987a-c998-11e4-a0b9-22000b6a88d2" - update.author # "umbrae" + update.thread # LiveThread(id="ukaeu1ik4sw5") + update.id # "7827987a-c998-11e4-a0b9-22000b6a88d2" + update.author # "umbrae" - If you don't need the object fetched right away (e.g., to utilize a - class method) you can do: + If you don't need the object fetched right away (e.g., to utilize a class + method) you can do: .. code-block:: python thread = await reddit.live("ukaeu1ik4sw5") update = await thread.get_update("7827987a-c998-11e4-a0b9-22000b6a88d2", lazy=True) update.contrib # LiveUpdateContribution instance + """ update = LiveUpdate(self._reddit, self.id, update_id) if not lazy: @@ -408,6 +413,7 @@ def __init__( :param reddit: An instance of :class:`.Reddit`. :param id: A live thread ID, e.g., ``"ukaeu1ik4sw5"`` + """ if (id, _data).count(None) != 1: raise TypeError("Either `id` or `_data` must be provided.") @@ -435,10 +441,11 @@ def discussions( ) -> AsyncIterator["asyncpraw.models.Submission"]: """Get submissions linking to the thread. - :param generator_kwargs: keyword arguments passed to - :class:`.ListingGenerator` constructor. - :returns: A :class:`.ListingGenerator` object which yields - :class:`.Submission` object. + :param generator_kwargs: keyword arguments passed to :class:`.ListingGenerator` + constructor. + + :returns: A :class:`.ListingGenerator` object which yields :class:`.Submission` + object. Additional keyword arguments are passed in the initialization of :class:`.ListingGenerator`. @@ -459,8 +466,7 @@ async def report(self, type: str): # pylint: disable=redefined-builtin """Report the thread violating the Reddit rules. :param type: One of ``"spam"``, ``"vote-manipulation"``, - ``"personal-information"``, ``"sexualizing-minors"``, - ``"site-breaking"``. + ``"personal-information"``, ``"sexualizing-minors"``, ``"site-breaking"``. Usage: @@ -478,10 +484,11 @@ async def updates( ) -> AsyncIterator["asyncpraw.models.LiveUpdate"]: """Return a :class:`.ListingGenerator` yields :class:`.LiveUpdate` s. - :param generator_kwargs: keyword arguments passed to - :class:`.ListingGenerator` constructor. - :returns: A :class:`.ListingGenerator` object which yields - :class:`.LiveUpdate` object. + :param generator_kwargs: keyword arguments passed to :class:`.ListingGenerator` + constructor. + + :returns: A :class:`.ListingGenerator` object which yields :class:`.LiveUpdate` + object. Additional keyword arguments are passed in the initialization of :class:`.ListingGenerator`. @@ -510,8 +517,8 @@ def __init__(self, thread: "asyncpraw.models.LiveThread"): :param thread: An instance of :class:`.LiveThread`. - This instance can be retrieved through ``thread.contrib`` - where thread is a :class:`.LiveThread` instance. E.g., + This instance can be retrieved through ``thread.contrib`` where thread is a + :class:`.LiveThread` instance. E.g., .. code-block:: python @@ -562,19 +569,18 @@ async def update( """Update settings of the live thread. :param title: (Optional) The title of the live thread (default: None). - :param description: (Optional) The live thread's description + :param description: (Optional) The live thread's description (default: None). + :param nsfw: (Optional) Indicate whether this thread is not safe for work (default: None). - :param nsfw: (Optional) Indicate whether this thread is not safe for - work (default: None). - :param resources: (Optional) Markdown formatted information that is - useful for the live thread (default: None). + :param resources: (Optional) Markdown formatted information that is useful for + the live thread (default: None). Does nothing if no arguments are provided. Each setting will maintain its current value if ``None`` is specified. - Additional keyword arguments can be provided to handle new settings as - Reddit introduces them. + Additional keyword arguments can be provided to handle new settings as Reddit + introduces them. Usage: @@ -585,8 +591,8 @@ async def update( # update `title` and `nsfw` updated_thread = await thread.contrib.update(title=new_title, nsfw=True) - If Reddit introduces new settings, you must specify ``None`` for the - setting you want to maintain: + If Reddit introduces new settings, you must specify ``None`` for the setting you + want to maintain: .. code-block:: python @@ -632,6 +638,7 @@ def __init__(self, live_thread: "asyncpraw.models.LiveThread"): """Create a LiveThreadStream instance. :param live_thread: The live thread associated with the stream. + """ self.live_thread = live_thread @@ -640,19 +647,19 @@ def updates( ) -> AsyncIterator["asyncpraw.models.LiveUpdate"]: """Yield new updates to the live thread as they become available. - :param skip_existing: Set to ``True`` to only fetch items created - after the stream (default: ``False``). + :param skip_existing: Set to ``True`` to only fetch items created after the + stream (default: ``False``). As with :meth:`.LiveThread.updates()`, updates are yielded as :class:`.LiveUpdate`. - Updates are yielded oldest first. Up to 100 historical updates will - initially be returned. + Updates are yielded oldest first. Up to 100 historical updates will initially be + returned. Keyword arguments are passed to :func:`.stream_generator`. - For example, to retrieve all new updates made to the - ``"ta535s1hq2je"`` live thread, try: + For example, to retrieve all new updates made to the ``"ta535s1hq2je"`` live + thread, try: .. code-block:: python @@ -660,8 +667,8 @@ def updates( async for live_update in live.stream.updates(): print(live_update.body) - To only retrieve new updates starting from when the stream is - created, pass ``skip_existing=True``: + To only retrieve new updates starting from when the stream is created, pass + ``skip_existing=True``: .. code-block:: python @@ -678,24 +685,24 @@ class LiveUpdate(FullnameMixin, RedditBase): **Typical Attributes** - This table describes attributes that typically belong to objects of this - class. Since attributes are dynamically provided (see - :ref:`determine-available-attributes-of-an-object`), there is not a - guarantee that these attributes will always be present, nor is this list - necessarily complete. - - ======================= =================================================== - Attribute Description - ======================= =================================================== - ``author`` The :class:`.Redditor` who made the update. - ``body`` Body of the update, as Markdown. - ``body_html`` Body of the update, as HTML. - ``created_utc`` The time the update was created, as `Unix Time`_. - ``stricken`` A ``bool`` representing whether or not the update - was stricken (see :meth:`.strike`). - ======================= =================================================== - - .. _Unix Time: https://en.wikipedia.org/wiki/Unix_time + This table describes attributes that typically belong to objects of this class. + Since attributes are dynamically provided (see + :ref:`determine-available-attributes-of-an-object`), there is not a guarantee that + these attributes will always be present, nor is this list necessarily complete. + + =============== =================================================================== + Attribute Description + =============== =================================================================== + ``author`` The :class:`.Redditor` who made the update. + ``body`` Body of the update, as Markdown. + ``body_html`` Body of the update, as HTML. + ``created_utc`` The time the update was created, as `Unix Time`_. + ``stricken`` A ``bool`` representing whether or not the update was stricken (see + :meth:`.strike`). + =============== =================================================================== + + .. _unix time: https://en.wikipedia.org/wiki/Unix_time + """ STR_FIELD = "id" @@ -734,7 +741,8 @@ def __init__( :param reddit: An instance of :class:`.Reddit`. :param thread_id: A live thread ID, e.g., ``"ukaeu1ik4sw5"``. - :param update_id: A live update ID, e.g., ``"7827987a-c998-11e4-a0b9-22000b6a88d2"``. + :param update_id: A live update ID, e.g., + ``"7827987a-c998-11e4-a0b9-22000b6a88d2"``. Usage: @@ -742,9 +750,10 @@ def __init__( update = LiveUpdate(reddit, "ukaeu1ik4sw5", "7827987a-c998-11e4-a0b9-22000b6a88d2") await update.load() - update.thread # LiveThread(id="ukaeu1ik4sw5") - update.id # "7827987a-c998-11e4-a0b9-22000b6a88d2" - update.author # "umbrae" + update.thread # LiveThread(id="ukaeu1ik4sw5") + update.id # "7827987a-c998-11e4-a0b9-22000b6a88d2" + update.author # "umbrae" + """ if _data is not None: # Since _data (part of JSON returned from reddit) have no thread ID, @@ -782,8 +791,8 @@ def __init__(self, update: "asyncpraw.models.LiveUpdate"): :param update: An instance of :class:`.LiveUpdate`. - This instance can be retrieved through ``update.contrib`` - where update is a :class:`.LiveUpdate` instance. E.g., + This instance can be retrieved through ``update.contrib`` where update is a + :class:`.LiveUpdate` instance. E.g., .. code-block:: python @@ -825,8 +834,8 @@ async def strike(self): .. note:: - Accessing lazy attributes on updates (includes ``update.stricken``) - may raise :py:class:`AttributeError`. See :class:`.LiveUpdate` for details. + Accessing lazy attributes on updates (includes ``update.stricken``) may + raise :py:class:`AttributeError`. See :class:`.LiveUpdate` for details. """ url = API_PATH["live_strike"].format(id=self.update.thread.id) diff --git a/asyncpraw/models/reddit/message.py b/asyncpraw/models/reddit/message.py index bac540cc8..e85c33420 100644 --- a/asyncpraw/models/reddit/message.py +++ b/asyncpraw/models/reddit/message.py @@ -16,30 +16,27 @@ class Message(InboxableMixin, ReplyableMixin, FullnameMixin, RedditBase): **Typical Attributes** - This table describes attributes that typically belong to objects of this - class. Since attributes are dynamically provided (see - :ref:`determine-available-attributes-of-an-object`), there is not a - guarantee that these attributes will always be present, nor is this list - necessarily complete. - - ======================= =================================================== - Attribute Description - ======================= =================================================== - ``author`` Provides an instance of :class:`.Redditor`. - ``body`` The body of the message, as Markdown. - ``body_html`` The body of the message, as HTML. - ``created_utc`` Time the message was created, represented in - `Unix Time`_. - ``dest`` Provides an instance of :class:`.Redditor`. The - recipient of the message. - ``id`` The ID of the message. - ``name`` The full ID of the message, prefixed with ``t4_``. - ``subject`` The subject of the message. - ``was_comment`` Whether or not the message was a comment reply. - ======================= =================================================== - - - .. _Unix Time: https://en.wikipedia.org/wiki/Unix_time + This table describes attributes that typically belong to objects of this class. + Since attributes are dynamically provided (see + :ref:`determine-available-attributes-of-an-object`), there is not a guarantee that + these attributes will always be present, nor is this list necessarily complete. + + =============== ================================================================ + Attribute Description + =============== ================================================================ + ``author`` Provides an instance of :class:`.Redditor`. + ``body`` The body of the message, as Markdown. + ``body_html`` The body of the message, as HTML. + ``created_utc`` Time the message was created, represented in `Unix Time`_. + ``dest`` Provides an instance of :class:`.Redditor`. The recipient of the + message. + ``id`` The ID of the message. + ``name`` The full ID of the message, prefixed with ``t4_``. + ``subject`` The subject of the message. + ``was_comment`` Whether or not the message was a comment reply. + =============== ================================================================ + + .. _unix time: https://en.wikipedia.org/wiki/Unix_time """ @@ -85,8 +82,10 @@ def __init__(self, reddit: "asyncpraw.Reddit", _data: Dict[str, Any]): async def delete(self): """Delete the message. - .. note:: Reddit does not return an indication of whether or not the - message was successfully deleted. + .. note:: + + Reddit does not return an indication of whether or not the message was + successfully deleted. For example, to delete the most recent message in your inbox: @@ -105,31 +104,29 @@ class SubredditMessage(Message): **Typical Attributes** - This table describes attributes that typically belong to objects of this - class. Since attributes are dynamically provided (see - :ref:`determine-available-attributes-of-an-object`), there is not a - guarantee that these attributes will always be present, nor is this list - necessarily complete. - - ======================= =================================================== - Attribute Description - ======================= =================================================== - ``author`` Provides an instance of :class:`.Redditor`. - ``body`` The body of the message, as Markdown. - ``body_html`` The body of the message, as HTML. - ``created_utc`` Time the message was created, represented in - `Unix Time`_. - ``dest`` Provides an instance of :class:`.Redditor`. The - recipient of the message. - ``id`` The ID of the message. - ``name`` The full ID of the message, prefixed with ``t4_``. - ``subject`` The subject of the message. - ``subreddit`` If the message was sent from a subreddit, - provides an instance of :class:`.Subreddit`. - ``was_comment`` Whether or not the message was a comment reply. - ======================= =================================================== - - .. _Unix Time: https://en.wikipedia.org/wiki/Unix_time + This table describes attributes that typically belong to objects of this class. + Since attributes are dynamically provided (see + :ref:`determine-available-attributes-of-an-object`), there is not a guarantee that + these attributes will always be present, nor is this list necessarily complete. + + =============== ================================================================= + Attribute Description + =============== ================================================================= + ``author`` Provides an instance of :class:`.Redditor`. + ``body`` The body of the message, as Markdown. + ``body_html`` The body of the message, as HTML. + ``created_utc`` Time the message was created, represented in `Unix Time`_. + ``dest`` Provides an instance of :class:`.Redditor`. The recipient of the + message. + ``id`` The ID of the message. + ``name`` The full ID of the message, prefixed with ``t4_``. + ``subject`` The subject of the message. + ``subreddit`` If the message was sent from a subreddit, provides an instance of + :class:`.Subreddit`. + ``was_comment`` Whether or not the message was a comment reply. + =============== ================================================================= + + .. _unix time: https://en.wikipedia.org/wiki/Unix_time """ @@ -142,10 +139,12 @@ async def mute(self): .. code-block:: python from asyncpraw.models import SubredditMessage + async for message in reddit.inbox.all(): if isinstance(message, SubredditMessage): await msg.mute() break + """ await self._reddit.post(API_PATH["mute_sender"], data={"id": self.fullname}) @@ -158,9 +157,11 @@ async def unmute(self): .. code-block:: python from asyncpraw.models import SubredditMessage + async for message in reddit.inbox.all(): if isinstance(message, SubredditMessage): await msg.unmute() break + """ await self._reddit.post(API_PATH["unmute_sender"], data={"id": self.fullname}) diff --git a/asyncpraw/models/reddit/mixins/__init__.py b/asyncpraw/models/reddit/mixins/__init__.py index 8a0f6d512..58ca764b5 100644 --- a/asyncpraw/models/reddit/mixins/__init__.py +++ b/asyncpraw/models/reddit/mixins/__init__.py @@ -25,8 +25,8 @@ async def _add_removal_reason(self, mod_note="", reason_id=None): :param mod_note: A message for the other moderators. :param reason_id: The removal reason ID. - It is necessary to first call :meth:`~.remove` on the - :class:`~.Comment` or :class:`~.Submission`. + It is necessary to first call :meth:`~.remove` on the :class:`~.Comment` or + :class:`~.Submission`. If ``reason_id`` is not specified, ``mod_note`` cannot be blank. @@ -46,10 +46,9 @@ async def _add_removal_reason(self, mod_note="", reason_id=None): async def approve(self): """Approve a :class:`~.Comment` or :class:`~.Submission`. - Approving a comment or submission reverts a removal, resets the report - counter, adds a green check mark indicator (only visible to other - moderators) on the website view, and sets the ``approved_by`` attribute - to the authenticated user. + Approving a comment or submission reverts a removal, resets the report counter, + adds a green check mark indicator (only visible to other moderators) on the + website view, and sets the ``approved_by`` attribute to the authenticated user. Example usage: @@ -70,12 +69,12 @@ async def approve(self): async def distinguish(self, how="yes", sticky=False): """Distinguish a :class:`~.Comment` or :class:`~.Submission`. - :param how: One of "yes", "no", "admin", "special". "yes" adds a - moderator level distinguish. "no" removes any distinction. "admin" - and "special" require special user privileges to use. - :param sticky: Comment is stickied if ``True``, placing it at the top - of the comment page regardless of score. If thing is not a - top-level comment, this parameter is silently ignored. + :param how: One of "yes", "no", "admin", "special". "yes" adds a moderator level + distinguish. "no" removes any distinction. "admin" and "special" require + special user privileges to use. + :param sticky: Comment is stickied if ``True``, placing it at the top of the + comment page regardless of score. If thing is not a top-level comment, this + parameter is silently ignored. Example usage: @@ -88,7 +87,9 @@ async def distinguish(self, how="yes", sticky=False): submission = await reddit.submission(id="5or86n", lazy=True) await submission.mod.distinguish(how="no") - .. seealso:: :meth:`~.undistinguish` + .. seealso:: + + :meth:`~.undistinguish` """ data = {"how": how, "id": self.thing.fullname} @@ -100,10 +101,9 @@ async def distinguish(self, how="yes", sticky=False): async def ignore_reports(self): """Ignore future reports on a :class:`~.Comment` or :class:`~.Submission`. - Calling this method will prevent future reports on this Comment or - Submission from both triggering notifications and appearing in the - various moderation listings. The report count will still increment on - the Comment or Submission. + Calling this method will prevent future reports on this Comment or Submission + from both triggering notifications and appearing in the various moderation + listings. The report count will still increment on the Comment or Submission. Example usage: @@ -116,7 +116,9 @@ async def ignore_reports(self): submission = await reddit.submission(id="5or86n", lazy=True) await submission.mod.ignore_reports() - .. seealso:: :meth:`~.unignore_reports` + .. seealso:: + + :meth:`~.unignore_reports` """ await self.thing._reddit.post( @@ -137,7 +139,9 @@ async def lock(self): submission = await reddit.submission(id="5or86n", lazy=True) await submission.mod.lock() - .. seealso:: :meth:`~.unlock` + .. seealso:: + + :meth:`~.unlock` """ await self.thing._reddit.post( @@ -148,12 +152,12 @@ async def remove(self, spam=False, mod_note="", reason_id=None): """Remove a :class:`~.Comment` or :class:`~.Submission`. :param mod_note: A message for the other moderators. - :param spam: When True, use the removal to help train the Subreddit's - spam filter (default: False). + :param spam: When True, use the removal to help train the Subreddit's spam + filter (default: False). :param reason_id: The removal reason ID. - If either ``reason_id`` or ``mod_note`` are provided, a second API - call is made to add the removal reason. + If either ``reason_id`` or ``mod_note`` are provided, a second API call is made + to add the removal reason. Example usage: @@ -185,23 +189,24 @@ async def send_removal_message( ): """Send a removal message for a :class:`~.Comment` or :class:`~.Submission`. - .. warning:: The object has to be removed before giving it a removal - reason. Remove the object with :meth:`.remove`. Trying to add a - removal reason without removing the object will result in - :class:`.RedditAPIException` being thrown with an ``INVALID_ID`` - error_type. + .. warning:: + + The object has to be removed before giving it a removal reason. Remove the + object with :meth:`.remove`. Trying to add a removal reason without removing + the object will result in :class:`.RedditAPIException` being thrown with an + ``INVALID_ID`` error_type. Reddit adds human-readable information about the object to the message. - :param type: One of "public", "private", "private_exposed". - "public" leaves a stickied comment on the post. - "private" sends a Modmail message with hidden username. - "private_exposed" sends a Modmail message without hidden username. - :param title: The short reason given in the message. - (Ignored if type is "public".) + :param type: One of "public", "private", "private_exposed". "public" leaves a + stickied comment on the post. "private" sends a Modmail message with hidden + username. "private_exposed" sends a Modmail message without hidden username. + :param title: The short reason given in the message. (Ignored if type is + "public".) :param message: The body of the message. If ``type`` is "public", the new :class:`~.Comment` is returned. + """ # The API endpoint used to send removal messages is different for posts and # comments, so the derived classes specify which one. @@ -235,7 +240,9 @@ async def undistinguish(self): submission = await reddit.submission(id="5or86n", lazy=True) await submission.mod.undistinguish() - .. seealso:: :meth:`~.distinguish` + .. seealso:: + + :meth:`~.distinguish` """ await self.distinguish(how="no") @@ -243,9 +250,8 @@ async def undistinguish(self): async def unignore_reports(self): """Resume receiving future reports on a Comment or Submission. - Future reports on this :class:`~.Comment` or :class:`~.Submission` - will cause notifications, and appear in the various moderation - listings. + Future reports on this :class:`~.Comment` or :class:`~.Submission` will cause + notifications, and appear in the various moderation listings. Example usage: @@ -258,7 +264,9 @@ async def unignore_reports(self): submission = await reddit.submission(id="5or86n", lazy=True) await submission.mod.unignore_reports() - .. seealso:: :meth:`~.ignore_reports` + .. seealso:: + + :meth:`~.ignore_reports` """ await self.thing._reddit.post( @@ -279,7 +287,9 @@ async def unlock(self): submission = await reddit.submission(id="5or86n", lazy=True) await submission.mod.unlock() - .. seealso:: :meth:`~.lock` + .. seealso:: + + :meth:`~.lock` """ await self.thing._reddit.post( diff --git a/asyncpraw/models/reddit/mixins/editable.py b/asyncpraw/models/reddit/mixins/editable.py index 43161b6ea..3854eefd9 100644 --- a/asyncpraw/models/reddit/mixins/editable.py +++ b/asyncpraw/models/reddit/mixins/editable.py @@ -25,6 +25,7 @@ async def edit(self, body): """Replace the body of the object with ``body``. :param body: The Markdown formatted content for the updated object. + :returns: The current instance after updating its attributes. Example usage: diff --git a/asyncpraw/models/reddit/mixins/fullname.py b/asyncpraw/models/reddit/mixins/fullname.py index babe4f239..9ceb2a156 100644 --- a/asyncpraw/models/reddit/mixins/fullname.py +++ b/asyncpraw/models/reddit/mixins/fullname.py @@ -10,8 +10,8 @@ class FullnameMixin: def fullname(self) -> str: """Return the object's fullname. - A fullname is an object's kind mapping like ``t3`` followed by an - underscore and the object's base36 ID, e.g., ``t1_c5s96e0``. + A fullname is an object's kind mapping like ``t3`` followed by an underscore and + the object's base36 ID, e.g., ``t1_c5s96e0``. """ return f"{self._kind}_{self.id}" diff --git a/asyncpraw/models/reddit/mixins/gildable.py b/asyncpraw/models/reddit/mixins/gildable.py index 7fdf84047..d2f308fef 100644 --- a/asyncpraw/models/reddit/mixins/gildable.py +++ b/asyncpraw/models/reddit/mixins/gildable.py @@ -17,6 +17,7 @@ async def award( :param is_anonymous: If True, the authenticated user's username will not be revealed to the recipient. :param message: Message to include with the award. + :returns: A dict containing info similar to what is shown below: .. code-block:: python @@ -61,6 +62,7 @@ async def award( ], } + Requires the authenticated user to own Reddit Coins. Calling this method will consume Reddit Coins. diff --git a/asyncpraw/models/reddit/mixins/inboxable.py b/asyncpraw/models/reddit/mixins/inboxable.py index 9438ba0e1..27bd5e8a3 100644 --- a/asyncpraw/models/reddit/mixins/inboxable.py +++ b/asyncpraw/models/reddit/mixins/inboxable.py @@ -9,7 +9,9 @@ class InboxableMixin: async def block(self): """Block the user who sent the item. - .. note:: This method pertains only to objects which were retrieved via the inbox. + .. note:: + + This method pertains only to objects which were retrieved via the inbox. Example usage: @@ -32,7 +34,6 @@ async def collapse(self): This method pertains only to objects which were retrieved via the inbox. - Example usage: .. code-block:: python @@ -44,7 +45,9 @@ async def collapse(self): await message.collapse() break - .. seealso:: :meth:`~.uncollapse` + .. seealso:: + + :meth:`~.uncollapse` """ await self._reddit.inbox.collapse([self]) @@ -52,8 +55,9 @@ async def collapse(self): async def mark_read(self): """Mark a single inbox item as read. - .. note:: This method pertains only to objects which were retrieved via - the inbox. + .. note:: + + This method pertains only to objects which were retrieved via the inbox. Example usage: @@ -65,10 +69,12 @@ async def mark_read(self): # process unread messages ... - .. seealso:: :meth:`~.mark_unread` + .. seealso:: + + :meth:`~.mark_unread` - To mark the whole inbox as read with a single network request, - use :meth:`asyncpraw.models.Inbox.mark_read` + To mark the whole inbox as read with a single network request, use + :meth:`asyncpraw.models.Inbox.mark_read` """ await self._reddit.inbox.mark_read([self]) @@ -76,8 +82,9 @@ async def mark_read(self): async def mark_unread(self): """Mark the item as unread. - .. note:: This method pertains only to objects which were retrieved via - the inbox. + .. note:: + + This method pertains only to objects which were retrieved via the inbox. Example usage: @@ -89,7 +96,9 @@ async def mark_unread(self): # process messages ... - .. seealso:: :meth:`~.mark_read` + .. seealso:: + + :meth:`~.mark_read` """ await self._reddit.inbox.mark_unread([self]) @@ -97,8 +106,9 @@ async def mark_unread(self): async def uncollapse(self): """Mark the item as uncollapsed. - .. note:: This method pertains only to objects which were retrieved via - the inbox. + .. note:: + + This method pertains only to objects which were retrieved via the inbox. Example usage: @@ -111,7 +121,9 @@ async def uncollapse(self): await message.uncollapse() break - .. seealso:: :meth:`~.collapse` + .. seealso:: + + :meth:`~.collapse` """ await self._reddit.inbox.uncollapse([self]) diff --git a/asyncpraw/models/reddit/mixins/inboxtoggleable.py b/asyncpraw/models/reddit/mixins/inboxtoggleable.py index 7f44e7082..bbf673186 100644 --- a/asyncpraw/models/reddit/mixins/inboxtoggleable.py +++ b/asyncpraw/models/reddit/mixins/inboxtoggleable.py @@ -18,7 +18,9 @@ async def disable_inbox_replies(self): submission = await reddit.submission("8dmv8z", lazy=True) await submission.disable_inbox_replies() - .. seealso:: :meth:`~.enable_inbox_replies` + .. seealso:: + + :meth:`~.enable_inbox_replies` """ await self._reddit.post( @@ -38,7 +40,9 @@ async def enable_inbox_replies(self): submission = await reddit.submission("8dmv8z", lazy=True) await submission.enable_inbox_replies() - .. seealso:: :meth:`~.disable_inbox_replies` + .. seealso:: + + :meth:`~.disable_inbox_replies` """ await self._reddit.post( diff --git a/asyncpraw/models/reddit/mixins/messageable.py b/asyncpraw/models/reddit/mixins/messageable.py index 5089a7e59..2c0e5c0ba 100644 --- a/asyncpraw/models/reddit/mixins/messageable.py +++ b/asyncpraw/models/reddit/mixins/messageable.py @@ -29,6 +29,7 @@ async def message( The authenticated user must be a moderator of the subreddit and have the ``mail`` moderator permission. + For example, to send a private message to ``u/spez``, try: .. code-block:: python @@ -47,8 +48,8 @@ async def message( .. code-block:: python - subreddit = await reddit.subreddit("test") - await subreddit.message("TEST", "test PM from Async PRAW") + subreddit = await reddit.subreddit("test") + await subreddit.message("TEST", "test PM from Async PRAW") """ data = { diff --git a/asyncpraw/models/reddit/mixins/replyable.py b/asyncpraw/models/reddit/mixins/replyable.py index 133cc2cc7..5a7f2645a 100644 --- a/asyncpraw/models/reddit/mixins/replyable.py +++ b/asyncpraw/models/reddit/mixins/replyable.py @@ -9,18 +9,20 @@ async def reply(self, body: str): """Reply to the object. :param body: The Markdown formatted content for a comment. - :returns: A :class:`~.Comment` object for the newly created - comment or ``None`` if Reddit doesn't provide one. - - A ``None`` value can be returned if the target is a comment or - submission in a quarantined subreddit and the authenticated user - has not opt-ed in to viewing the content. When this happens the - comment will be successfully created on Reddit and can be retried - by drawing the comment from the user's comment history. - - .. note:: Some items, such as locked submissions/comments or - non-replyable messages will throw - ``asyncprawcore.exceptions.Forbidden`` when attempting to reply + + :returns: A :class:`~.Comment` object for the newly created comment or ``None`` + if Reddit doesn't provide one. + + A ``None`` value can be returned if the target is a comment or submission in a + quarantined subreddit and the authenticated user has not opt-ed in to viewing + the content. When this happens the comment will be successfully created on + Reddit and can be retried by drawing the comment from the user's comment + history. + + .. note:: + + Some items, such as locked submissions/comments or non-replyable messages + will throw ``asyncprawcore.exceptions.Forbidden`` when attempting to reply to them. Example usage: diff --git a/asyncpraw/models/reddit/mixins/savable.py b/asyncpraw/models/reddit/mixins/savable.py index 85cb2c70e..d55ba61b1 100644 --- a/asyncpraw/models/reddit/mixins/savable.py +++ b/asyncpraw/models/reddit/mixins/savable.py @@ -10,9 +10,8 @@ class SavableMixin: async def save(self, category: Optional[str] = None): """Save the object. - :param category: (Premium) The category to save to. If your user does - not have Reddit Premium this value is ignored by Reddit - (default: ``None``). + :param category: (Premium) The category to save to. If your user does not have + Reddit Premium this value is ignored by Reddit (default: ``None``). Example usage: @@ -24,7 +23,9 @@ async def save(self, category: Optional[str] = None): comment = await reddit.comment(id="dxolpyc", lazy=True, lazy=True) await comment.save() - .. seealso:: :meth:`~.unsave` + .. seealso:: + + :meth:`~.unsave` """ await self._reddit.post( @@ -44,7 +45,9 @@ async def unsave(self): comment = await reddit.comment(id="dxolpyc", lazy=True) await comment.unsave() - .. seealso:: :meth:`~.save` + .. seealso:: + + :meth:`~.save` """ await self._reddit.post(API_PATH["unsave"], data={"id": self.fullname}) diff --git a/asyncpraw/models/reddit/mixins/votable.py b/asyncpraw/models/reddit/mixins/votable.py index 577f3466f..59b5a35f7 100644 --- a/asyncpraw/models/reddit/mixins/votable.py +++ b/asyncpraw/models/reddit/mixins/votable.py @@ -13,11 +13,13 @@ async def _vote(self, direction): async def clear_vote(self): """Clear the authenticated user's vote on the object. - .. note:: Votes must be cast by humans. That is, API clients proxying a - human's action one-for-one are OK, but bots deciding how to vote on - content or amplifying a human's vote are not. See the reddit rules - for more details on what constitutes vote cheating. [`Ref - `_] + .. note:: + + Votes must be cast by humans. That is, API clients proxying a human's action + one-for-one are OK, but bots deciding how to vote on content or amplifying a + human's vote are not. See the reddit rules for more details on what + constitutes vote cheating. [`Ref + `_] Example usage: @@ -35,11 +37,13 @@ async def clear_vote(self): async def downvote(self): """Downvote the object. - .. note:: Votes must be cast by humans. That is, API clients proxying a - human's action one-for-one are OK, but bots deciding how to vote on - content or amplifying a human's vote are not. See the reddit rules - for more details on what constitutes vote cheating. [`Ref - `_] + .. note:: + + Votes must be cast by humans. That is, API clients proxying a human's action + one-for-one are OK, but bots deciding how to vote on content or amplifying a + human's vote are not. See the reddit rules for more details on what + constitutes vote cheating. [`Ref + `_] Example usage: @@ -51,7 +55,9 @@ async def downvote(self): comment = await reddit.comment(id="dxolpyc", lazy=True) await comment.downvote() - .. seealso:: :meth:`~.upvote` + .. seealso:: + + :meth:`~.upvote` """ await self._vote(direction=-1) @@ -59,11 +65,13 @@ async def downvote(self): async def upvote(self): """Upvote the object. - .. note:: Votes must be cast by humans. That is, API clients proxying a - human's action one-for-one are OK, but bots deciding how to vote on - content or amplifying a human's vote are not. See the reddit rules - for more details on what constitutes vote cheating. [`Ref - `_] + .. note:: + + Votes must be cast by humans. That is, API clients proxying a human's action + one-for-one are OK, but bots deciding how to vote on content or amplifying a + human's vote are not. See the reddit rules for more details on what + constitutes vote cheating. [`Ref + `_] Example usage: @@ -75,7 +83,9 @@ async def upvote(self): comment = await reddit.comment(id="dxolpyc", lazy=True) await comment.upvote() - .. seealso:: :meth:`~.downvote` + .. seealso:: + + :meth:`~.downvote` """ await self._vote(direction=1) diff --git a/asyncpraw/models/reddit/modmail.py b/asyncpraw/models/reddit/modmail.py index 515aa209d..4ea2aad0c 100644 --- a/asyncpraw/models/reddit/modmail.py +++ b/asyncpraw/models/reddit/modmail.py @@ -14,44 +14,39 @@ class ModmailConversation(RedditBase): **Typical Attributes** - This table describes attributes that typically belong to objects of this - class. Since attributes are dynamically provided (see - :ref:`determine-available-attributes-of-an-object`), there is not a - guarantee that these attributes will always be present, nor is this list - necessarily complete. - - ======================= =================================================== - Attribute Description - ======================= =================================================== - ``authors`` Provides an ordered list of :class:`.Redditor` - instances. The authors of each message in the - modmail conversation. - ``id`` The ID of the ModmailConversation. - ``is_highlighted`` Whether or not the ModmailConversation is - highlighted. - ``is_internal`` Whether or not the ModmailConversation is a private - mod conversation. - ``last_mod_update`` Time of the last mod message reply, represented in - the `ISO 8601`_ standard with timezone. - ``last_updated`` Time of the last message reply, represented in - the `ISO 8601`_ standard with timezone. - ``last_user_update`` Time of the last user message reply, represented in - the `ISO 8601`_ standard with timezone. - ``num_messages`` The number of messages in the ModmailConversation. - ``obj_ids`` Provides a list of dictionaries representing - mod actions on the ModmailConversation. Each dict - contains attributes of "key" and "id". The key can - be either "messages" or "ModAction". ModAction - represents archiving/highlighting etc. - ``owner`` Provides an instance of :class:`.Subreddit`. The - subreddit that the ModmailConversation belongs to. - ``participant`` Provides an instance of :class:`.Redditor`. The - participating user in the ModmailConversation. - ``subject`` The subject of the ModmailConversation. - ======================= =================================================== - - - .. _ISO 8601: https://en.wikipedia.org/wiki/ISO_8601 + This table describes attributes that typically belong to objects of this class. + Since attributes are dynamically provided (see + :ref:`determine-available-attributes-of-an-object`), there is not a guarantee that + these attributes will always be present, nor is this list necessarily complete. + + ==================== =============================================================== + Attribute Description + ==================== =============================================================== + ``authors`` Provides an ordered list of :class:`.Redditor` instances. The + authors of each message in the modmail conversation. + ``id`` The ID of the ModmailConversation. + ``is_highlighted`` Whether or not the ModmailConversation is highlighted. + ``is_internal`` Whether or not the ModmailConversation is a private mod + conversation. + ``last_mod_update`` Time of the last mod message reply, represented in the `ISO + 8601`_ standard with timezone. + ``last_updated`` Time of the last message reply, represented in the `ISO 8601`_ + standard with timezone. + ``last_user_update`` Time of the last user message reply, represented in the `ISO + 8601`_ standard with timezone. + ``num_messages`` The number of messages in the ModmailConversation. + ``obj_ids`` Provides a list of dictionaries representing mod actions on the + ModmailConversation. Each dict contains attributes of "key" and + "id". The key can be either "messages" or "ModAction". + ModAction represents archiving/highlighting etc. + ``owner`` Provides an instance of :class:`.Subreddit`. The subreddit that + the ModmailConversation belongs to. + ``participant`` Provides an instance of :class:`.Redditor`. The participating + user in the ModmailConversation. + ``subject`` The subject of the ModmailConversation. + ==================== =============================================================== + + .. _iso 8601: https://en.wikipedia.org/wiki/ISO_8601 """ @@ -99,8 +94,8 @@ def parse( # pylint: disable=arguments-differ :param data: The structured data. :param reddit: An instance of :class:`.Reddit`. - :param convert_objects: If True, convert message and mod action data - into objects (default: True). + :param convert_objects: If True, convert message and mod action data into + objects (default: True). """ conversation = data["conversation"] @@ -130,8 +125,7 @@ def __init__( ): """Construct an instance of the ModmailConversation object. - :param mark_read: If True, conversation is marked as read - (default: False). + :param mark_read: If True, conversation is marked as read (default: False). """ if bool(id) == bool(_data): @@ -213,7 +207,6 @@ async def mute(self, num_days=3): conversation = await subreddit.modmail("2gmz") await conversation.mute(7) - """ if num_days != 3: # no need to pass params if it's the default params = {"num_hours": num_days * 24} @@ -228,8 +221,8 @@ async def read( ): # noqa: D207, D301 """Mark the conversation(s) as read. - :param other_conversations: A list of other conversations to mark - (default: None). + :param other_conversations: A list of other conversations to mark (default: + None). For example, to mark the conversation as read along with other recent conversations from the same user: @@ -250,12 +243,12 @@ async def reply( """Reply to the conversation. :param body: The Markdown formatted content for a message. - :param author_hidden: When True, author is hidden from non-moderators - (default: False). - :param internal: When True, message is a private moderator note, - hidden from non-moderators (default: False). - :returns: A :class:`~.ModmailMessage` object for the newly created - message. + :param author_hidden: When True, author is hidden from non-moderators (default: + False). + :param internal: When True, message is a private moderator note, hidden from + non-moderators (default: False). + + :returns: A :class:`~.ModmailMessage` object for the newly created message. For example, to reply to the non-mod user while hiding your username: @@ -333,8 +326,8 @@ async def unread( ): # noqa: D207, D301 """Mark the conversation(s) as unread. - :param other_conversations: A list of other conversations to mark - (default: None). + :param other_conversations: A list of other conversations to mark (default: + None). For example, to mark the conversation as unread along with other recent conversations from the same user: @@ -343,8 +336,7 @@ async def unread( subreddit = await reddit.subreddit("redditdev") conversation = await subreddit.modmail.conversation("2gmz") - await conversation.unread(\ -other_conversations=conversation.user.recent_convos) + await conversation.unread(other_conversations=conversation.user.recent_convos) """ data = {"conversationIds": self._build_conversation_list(other_conversations)} diff --git a/asyncpraw/models/reddit/multi.py b/asyncpraw/models/reddit/multi.py index 6f2682d19..e014335af 100644 --- a/asyncpraw/models/reddit/multi.py +++ b/asyncpraw/models/reddit/multi.py @@ -21,33 +21,33 @@ class Multireddit(SubredditListingMixin, RedditBase): **Typical Attributes** - This table describes attributes that typically belong to objects of this - class. Since attributes are dynamically provided (see - :ref:`determine-available-attributes-of-an-object`), there is not a - guarantee that these attributes will always be present, nor is this list - necessarily complete. - - ======================= =================================================== - Attribute Description - ======================= =================================================== - ``can_edit`` A ``bool`` representing whether or not the - authenticated user may edit the multireddit. - ``copied_from`` The multireddit that the multireddit was copied - from, if it exists, otherwise ``None``. - ``created_utc`` When the multireddit was created, in `Unix Time`_. - ``description_html`` The description of the multireddit, as HTML. - ``description_md`` The description of the multireddit, as Markdown. - ``display_name`` The display name of the multireddit. - ``name`` The name of the multireddit. - ``over_18`` A ``bool`` representing whether or not the - multireddit is restricted for users over 18. - ``subreddits`` A ``list`` of :class:`.Subreddit`\ s that make up - the multireddit. - ``visibility`` The visibility of the multireddit, either - ``private``, ``public``, or ``hidden``. - ======================= =================================================== - - .. _Unix Time: https://en.wikipedia.org/wiki/Unix_time + This table describes attributes that typically belong to objects of this class. + Since attributes are dynamically provided (see + :ref:`determine-available-attributes-of-an-object`), there is not a guarantee that + these attributes will always be present, nor is this list necessarily complete. + + ==================== ============================================================= + Attribute Description + ==================== ============================================================= + ``can_edit`` A ``bool`` representing whether or not the authenticated user + may edit the multireddit. + ``copied_from`` The multireddit that the multireddit was copied from, if it + exists, otherwise ``None``. + ``created_utc`` When the multireddit was created, in `Unix Time`_. + ``description_html`` The description of the multireddit, as HTML. + ``description_md`` The description of the multireddit, as Markdown. + ``display_name`` The display name of the multireddit. + ``name`` The name of the multireddit. + ``over_18`` A ``bool`` representing whether or not the multireddit is + restricted for users over 18. + ``subreddits`` A ``list`` of :class:`.Subreddit`\ s that make up the + multireddit. + ``visibility`` The visibility of the multireddit, either ``private``, + ``public``, or ``hidden``. + ==================== ============================================================= + + .. _unix time: https://en.wikipedia.org/wiki/Unix_time + """ STR_FIELD = "path" @@ -74,8 +74,8 @@ def sluggify(title: str): def stream(self) -> SubredditStream: """Provide an instance of :class:`.SubredditStream`. - Streams can be used to indefinitely retrieve new comments made to a - multireddit, like: + Streams can be used to indefinitely retrieve new comments made to a multireddit, + like: .. code-block:: python @@ -83,8 +83,8 @@ def stream(self) -> SubredditStream: async for comment in multireddit.stream.comments(): print(comment) - Additionally, new submissions can be retrieved via the stream. In the - following example all new submissions to the multireddit are fetched: + Additionally, new submissions can be retrieved via the stream. In the following + example all new submissions to the multireddit are fetched: .. code-block:: python @@ -155,10 +155,10 @@ async def copy( ) -> "asyncpraw.models.Multireddit": """Copy this multireddit and return the new multireddit. - :param display_name: (optional) The display name for the copied - multireddit. Reddit will generate the ``name`` field from this - display name. When not provided the copy will use the same display - name and name as this multireddit. + :param display_name: (optional) The display name for the copied multireddit. + Reddit will generate the ``name`` field from this display name. When not + provided the copy will use the same display name and name as this + multireddit. To copy the multireddit ``bboe/test`` with a name of ``testing``: @@ -205,8 +205,7 @@ async def remove(self, subreddit: "asyncpraw.models.Subreddit"): :param subreddit: The subreddit to remove from this multi. - For example, to remove subreddit ``r/test`` from multireddit - ``bboe/test``: + For example, to remove subreddit ``r/test`` from multireddit ``bboe/test``: .. code-block:: python @@ -214,7 +213,6 @@ async def remove(self, subreddit: "asyncpraw.models.Subreddit"): multireddit = await reddit.multireddit("bboe", "test") await multireddit.remove(subreddit) - """ await self._ensure_author_fetched() url = API_PATH["multireddit_update"].format( @@ -231,21 +229,20 @@ async def update( ): """Update this multireddit. - Keyword arguments are passed for settings that should be updated. They - can any of: + Keyword arguments are passed for settings that should be updated. They can any + of: - :param display_name: The display name for this multireddit. Must be no - longer than 50 characters. + :param display_name: The display name for this multireddit. Must be no longer + than 50 characters. :param subreddits: Subreddits for this multireddit. - :param description_md: Description for this multireddit, formatted in - Markdown. - :param icon_name: Can be one of: ``art and design``, ``ask``, - ``books``, ``business``, ``cars``, ``comics``, ``cute animals``, - ``diy``, ``entertainment``, ``food and drink``, ``funny``, - ``games``, ``grooming``, ``health``, ``life advice``, ``military``, - ``models pinup``, ``music``, ``news``, ``philosophy``, ``pictures - and gifs``, ``science``, ``shopping``, ``sports``, ``style``, - ``tech``, ``travel``, ``unusual stories``, ``video``, or ``None``. + :param description_md: Description for this multireddit, formatted in Markdown. + :param icon_name: Can be one of: ``art and design``, ``ask``, ``books``, + ``business``, ``cars``, ``comics``, ``cute animals``, ``diy``, + ``entertainment``, ``food and drink``, ``funny``, ``games``, ``grooming``, + ``health``, ``life advice``, ``military``, ``models pinup``, ``music``, + ``news``, ``philosophy``, ``pictures and gifs``, ``science``, ``shopping``, + ``sports``, ``style``, ``tech``, ``travel``, ``unusual stories``, ``video``, + or ``None``. :param key_color: RGB hex color code of the form ``"#FFFFFF"``. :param visibility: Can be one of: ``hidden``, ``private``, ``public``. :param weighting_scheme: Can be one of: ``classic``, ``fresh``. diff --git a/asyncpraw/models/reddit/poll.py b/asyncpraw/models/reddit/poll.py index 01570334e..96a4f14ce 100644 --- a/asyncpraw/models/reddit/poll.py +++ b/asyncpraw/models/reddit/poll.py @@ -8,8 +8,7 @@ class PollOption(AsyncPRAWBase): """Class to represent one option of a poll. - If ``submission`` is a poll :class:`.Submission`, access the poll's - options like so: + If ``submission`` is a poll :class:`.Submission`, access the poll's options like so: .. code-block:: python @@ -23,19 +22,19 @@ class PollOption(AsyncPRAWBase): **Typical Attributes** - This table describes attributes that typically belong to objects of this - class. Since attributes are dynamically provided (see - :ref:`determine-available-attributes-of-an-object`), there is not a - guarantee that these attributes will always be present, nor is this list - necessarily complete. - - =================== ======================================================= - Attribute Description - =================== ======================================================= - ``id`` ID of the poll option. - ``text`` The text of the poll option. - ``vote_count`` The number of votes the poll option has received. - =================== ======================================================= + This table describes attributes that typically belong to objects of this class. + Since attributes are dynamically provided (see + :ref:`determine-available-attributes-of-an-object`), there is not a guarantee that + these attributes will always be present, nor is this list necessarily complete. + + ============== ================================================= + Attribute Description + ============== ================================================= + ``id`` ID of the poll option. + ``text`` The text of the poll option. + ``vote_count`` The number of votes the poll option has received. + ============== ================================================= + """ def __repr__(self): @@ -50,47 +49,45 @@ def __str__(self): class PollData(AsyncPRAWBase): """Class to represent poll data on a poll submission. - If ``submission`` is a poll :class:`.Submission`, access the poll data - like so: + If ``submission`` is a poll :class:`.Submission`, access the poll data like so: .. code-block:: python poll_data = submission.poll_data - print(f"There are {poll_data.total_vote_count} votes total." ) + print(f"There are {poll_data.total_vote_count} votes total.") print("The options are:") for option in poll_data.options: - print(f"{option} ({option.vote_count} votes)" ) - print(f"I voted for {poll_data.user_selection}." ) + print(f"{option} ({option.vote_count} votes)") + print(f"I voted for {poll_data.user_selection}.") **Typical Attributes** - This table describes attributes that typically belong to objects of this - class. Since attributes are dynamically provided (see - :ref:`determine-available-attributes-of-an-object`), there is not a - guarantee that these attributes will always be present, nor is this list - necessarily complete. - - =========================== =============================================== - Attribute Description - =========================== =============================================== - ``options`` A list of :class:`.PollOption` of the poll. - ``total_vote_count`` The total number of votes cast in the poll. - ``user_selection`` The poll option selected by the authenticated - user (possibly ``None``). - ``voting_end_timestamp`` Time the poll voting closes, represented in - `Unix Time`_. - =========================== =============================================== - - - .. _Unix Time: https://en.wikipedia.org/wiki/Unix_time + This table describes attributes that typically belong to objects of this class. + Since attributes are dynamically provided (see + :ref:`determine-available-attributes-of-an-object`), there is not a guarantee that + these attributes will always be present, nor is this list necessarily complete. + + ======================== ========================================================= + Attribute Description + ======================== ========================================================= + ``options`` A list of :class:`.PollOption` of the poll. + ``total_vote_count`` The total number of votes cast in the poll. + ``user_selection`` The poll option selected by the authenticated user + (possibly ``None``). + ``voting_end_timestamp`` Time the poll voting closes, represented in `Unix Time`_. + ======================== ========================================================= + + .. _unix time: https://en.wikipedia.org/wiki/Unix_time + """ @cachedproperty def user_selection(self) -> Optional[PollOption]: """Get the user's selection in this poll, if any. - :returns: The user's selection as a :class:`.PollOption`, or ``None`` - if there is no choice. + :returns: The user's selection as a :class:`.PollOption`, or ``None`` if there + is no choice. + """ if self._user_selection is None: return None @@ -108,6 +105,7 @@ def option(self, option_id: str) -> PollOption: """Get the option with the specified ID. :param option_id: The ID of a poll option, as a ``str``. + :returns: The specified :class:`.PollOption`. :raises: :py:class:`KeyError` if no option exists with the specified ID. diff --git a/asyncpraw/models/reddit/redditor.py b/asyncpraw/models/reddit/redditor.py index 744a98bf6..d1bbd3c55 100644 --- a/asyncpraw/models/reddit/redditor.py +++ b/asyncpraw/models/reddit/redditor.py @@ -18,59 +18,57 @@ class Redditor(MessageableMixin, RedditorListingMixin, FullnameMixin, RedditBase **Typical Attributes** - This table describes attributes that typically belong to objects of this - class. Since attributes are dynamically provided (see - :ref:`determine-available-attributes-of-an-object`), there is not a - guarantee that these attributes will always be present, nor is this list - necessarily complete. - - .. note:: Shadowbanned accounts are treated the same as non-existent - accounts, meaning that they will not have any attributes. - - .. note:: Suspended/banned accounts will only return the ``name`` and - ``is_suspended`` attributes. - - ==================================== ====================================== - Attribute Description - ==================================== ====================================== - ``comment_karma`` The comment karma for the Redditor. - ``comments`` Provide an instance of - :class:`.SubListing` for comment - access. - ``created_utc`` Time the account was created, - represented in `Unix Time`_. - ``has_verified_email`` Whether or not the Redditor has - verified their email. - ``icon_img`` The url of the Redditors' avatar. - ``id`` The ID of the Redditor. - ``is_employee`` Whether or not the Redditor is a - Reddit employee. - ``is_friend`` Whether or not the Redditor is friends - with the authenticated user. - ``is_mod`` Whether or not the Redditor mods any - subreddits. - ``is_gold`` Whether or not the Redditor has active - Reddit Premium status. - ``is_suspended`` Whether or not the Redditor is - currently suspended. - ``link_karma`` The link karma for the Redditor. - ``name`` The Redditor's username. - ``subreddit`` If the Redditor has created a - user-subreddit, provides a dictionary - of additional attributes. See below. - ``subreddit["banner_img"]`` The URL of the user-subreddit banner. - ``subreddit["name"]`` The fullname of the user-subreddit. - ``subreddit["over_18"]`` Whether or not the user-subreddit is - NSFW. - ``subreddit["public_description"]`` The public description of the user- - subreddit. - ``subreddit["subscribers"]`` The number of users subscribed to the - user-subreddit. - ``subreddit["title"]`` The title of the user-subreddit. - ==================================== ====================================== - - - .. _Unix Time: https://en.wikipedia.org/wiki/Unix_time + This table describes attributes that typically belong to objects of this class. + Since attributes are dynamically provided (see + :ref:`determine-available-attributes-of-an-object`), there is not a guarantee that + these attributes will always be present, nor is this list necessarily complete. + + .. note:: + + Shadowbanned accounts are treated the same as non-existent accounts, meaning + that they will not have any attributes. + + .. note:: + + Suspended/banned accounts will only return the ``name`` and ``is_suspended`` + attributes. + + =================================== ================================================ + Attribute Description + =================================== ================================================ + ``comment_karma`` The comment karma for the Redditor. + ``comments`` Provide an instance of :class:`.SubListing` for + comment access. + ``created_utc`` Time the account was created, represented in + `Unix Time`_. + ``has_verified_email`` Whether or not the Redditor has verified their + email. + ``icon_img`` The url of the Redditors' avatar. + ``id`` The ID of the Redditor. + ``is_employee`` Whether or not the Redditor is a Reddit + employee. + ``is_friend`` Whether or not the Redditor is friends with the + authenticated user. + ``is_mod`` Whether or not the Redditor mods any subreddits. + ``is_gold`` Whether or not the Redditor has active Reddit + Premium status. + ``is_suspended`` Whether or not the Redditor is currently + suspended. + ``link_karma`` The link karma for the Redditor. + ``name`` The Redditor's username. + ``subreddit`` If the Redditor has created a user-subreddit, + provides a dictionary of additional attributes. + See below. + ``subreddit["banner_img"]`` The URL of the user-subreddit banner. + ``subreddit["name"]`` The fullname of the user-subreddit. + ``subreddit["over_18"]`` Whether or not the user-subreddit is NSFW. + ``subreddit["public_description"]`` The public description of the user- subreddit. + ``subreddit["subscribers"]`` The number of users subscribed to the + user-subreddit. + ``subreddit["title"]`` The title of the user-subreddit. + =================================== ================================================ + + .. _unix time: https://en.wikipedia.org/wiki/Unix_time """ @@ -87,8 +85,8 @@ def from_data(cls, reddit, data): def stream(self) -> "asyncpraw.models.reddit.redditor.RedditorStream": """Provide an instance of :class:`.RedditorStream`. - Streams can be used to indefinitely retrieve new comments made by a - redditor, like: + Streams can be used to indefinitely retrieve new comments made by a redditor, + like: .. code-block:: python @@ -96,9 +94,8 @@ def stream(self) -> "asyncpraw.models.reddit.redditor.RedditorStream": async for comment in redditor.stream.comments(): print(comment) - Additionally, new submissions can be retrieved via the stream. In the - following example all submissions are fetched via the redditor - ``spez``: + Additionally, new submissions can be retrieved via the stream. In the following + example all submissions are fetched via the redditor ``spez``: .. code-block:: python @@ -194,8 +191,8 @@ async def block(self): async def friend(self, note: str = None): """Friend the Redditor. - :param note: A note to save along with the relationship. Requires - Reddit Premium (default: None). + :param note: A note to save along with the relationship. Requires Reddit Premium + (default: None). Calling this method subsequent times will update the note. @@ -219,8 +216,8 @@ async def friend(self, note: str = None): async def friend_info(self) -> "asyncpraw.models.Redditor": """Return a Redditor instance with specific friend-related attributes. - :returns: A :class:`.Redditor` instance with fields ``date``, ``id``, - and possibly ``note`` if the authenticated user has Reddit Premium. + :returns: A :class:`.Redditor` instance with fields ``date``, ``id``, and + possibly ``note`` if the authenticated user has Reddit Premium. For example, to get the friendship information of Redditor ``spez``: @@ -236,8 +233,7 @@ async def friend_info(self) -> "asyncpraw.models.Redditor": async def gild(self, months: int = 1): """Gild the Redditor. - :param months: Specifies the number of months to gild up to 36 - (default: 1). + :param months: Specifies the number of months to gild up to 36 (default: 1). For example, to gild Redditor ``spez`` for 1 month: @@ -257,12 +253,13 @@ async def gild(self, months: int = 1): async def moderated(self) -> List["asyncpraw.models.Subreddit"]: """Return a list of the redditor's moderated subreddits. - :returns: A ``list`` of :class:`~asyncpraw.models.Subreddit` objects. - Return ``[]`` if the redditor has no moderated subreddits. + :returns: A ``list`` of :class:`~asyncpraw.models.Subreddit` objects. Return + ``[]`` if the redditor has no moderated subreddits. - .. note:: The redditor's own user profile subreddit will not be - returned, but other user profile subreddits they moderate - will be returned. + .. note:: + + The redditor's own user profile subreddit will not be returned, but other + user profile subreddits they moderate will be returned. Usage: @@ -293,15 +290,14 @@ async def multireddits(self) -> List["asyncpraw.models.Multireddit"]: redditor = await reddit.redditor("spez") multireddits = await redditor.multireddits() - """ return await self._reddit.get(API_PATH["multireddit_user"].format(user=self)) async def trophies(self) -> List["asyncpraw.models.Trophy"]: """Return a list of the redditor's trophies. - :returns: A ``list`` of :class:`~asyncpraw.models.Trophy` objects. - Return an empty list (``[]``) if the redditor has no trophies. + :returns: A ``list`` of :class:`~asyncpraw.models.Trophy` objects. Return an + empty list (``[]``) if the redditor has no trophies. :raises: :class:`.RedditAPIException` if the redditor doesn't exist. @@ -367,13 +363,12 @@ def comments( ) -> AsyncGenerator["asyncpraw.models.Comment", None]: """Yield new comments as they become available. - Comments are yielded oldest first. Up to 100 historical comments will - initially be returned. + Comments are yielded oldest first. Up to 100 historical comments will initially + be returned. Keyword arguments are passed to :func:`.stream_generator`. - For example, to retrieve all new comments made by redditor ``spez``, - try: + For example, to retrieve all new comments made by redditor ``spez``, try: .. code-block:: python @@ -389,19 +384,18 @@ def submissions( ) -> AsyncGenerator["asyncpraw.models.Submission", None]: """Yield new submissions as they become available. - Submissions are yielded oldest first. Up to 100 historical submissions - will initially be returned. + Submissions are yielded oldest first. Up to 100 historical submissions will + initially be returned. Keyword arguments are passed to :func:`.stream_generator`. - For example, to retrieve all new submissions made by redditor - ``spez``, try: + For example, to retrieve all new submissions made by redditor ``spez``, try: .. code-block:: python redditor = await reddit.redditor("spez") async for submission in redditor.stream.submissions(): - print(submission) + print(submission) """ return stream_generator(self.redditor.submissions.new, **stream_options) diff --git a/asyncpraw/models/reddit/removal_reasons.py b/asyncpraw/models/reddit/removal_reasons.py index 0cc3f6e46..8c9fe8e3b 100644 --- a/asyncpraw/models/reddit/removal_reasons.py +++ b/asyncpraw/models/reddit/removal_reasons.py @@ -15,19 +15,19 @@ class RemovalReason(RedditBase): **Typical Attributes** - This table describes attributes that typically belong to objects of this - class. Since attributes are dynamically provided (see - :ref:`determine-available-attributes-of-an-object`), there is not a - guarantee that these attributes will always be present, nor is this list - necessarily complete. - - ======================= =================================================== - Attribute Description - ======================= =================================================== - ``id`` The id of the removal reason. - ``message`` The message of the removal reason. - ``title`` The title of the removal reason. - ======================= =================================================== + This table describes attributes that typically belong to objects of this class. + Since attributes are dynamically provided (see + :ref:`determine-available-attributes-of-an-object`), there is not a guarantee that + these attributes will always be present, nor is this list necessarily complete. + + =========== ================================== + Attribute Description + =========== ================================== + ``id`` The id of the removal reason. + ``message`` The message of the removal reason. + ``title`` The title of the removal reason. + =========== ================================== + """ STR_FIELD = "id" @@ -37,8 +37,9 @@ def _warn_reason_id(reason_id_value: Optional[str], id_value: Optional[str]): """Reason id param is deprecated. Warns if it's used. :param reason_id_value: The value passed as parameter ``reason_id``. - :param id_value: Returns the actual value of parameter ``id`` is - parameter ``reason_id`` is not used. + :param id_value: Returns the actual value of parameter ``id`` is parameter + ``reason_id`` is not used. + """ if reason_id_value is not None: warn( @@ -75,9 +76,9 @@ def __init__( :param reddit: An instance of :class:`.Reddit`. :param subreddit: An instance of :class:`.Subreddit`. :param id: The id of the removal reason. - :param reason_id: (Deprecated) The original name of the ``id`` - parameter. Used for backwards compatibility. This parameter should - not be used. + :param reason_id: (Deprecated) The original name of the ``id`` parameter. Used + for backwards compatibility. This parameter should not be used. + """ id = self._warn_reason_id(reason_id, id) if (id, _data).count(None) != 1: @@ -116,7 +117,9 @@ async def delete(self): async def update(self, message: Optional[str] = None, title: Optional[str] = None): """Update the removal reason from this subreddit. - .. note:: Existing values will be used for any unspecified arguments. + .. note:: + + Existing values will be used for any unspecified arguments. :param message: The removal reason's new message. :param title: The removal reason's new title. @@ -158,14 +161,16 @@ async def get_reason( reason = await subreddit.mod.removal_reasons.get_reason(reason_id) print(reason) - You can also use indices to get a numbered removal reason. Since Python - uses 0-indexing, the first removal reason is index 0, and so on. + You can also use indices to get a numbered removal reason. Since Python uses + 0-indexing, the first removal reason is index 0, and so on. - .. note:: Both negative indices and slices can be used to interact with - the removal reasons. + .. note:: - :raises: :py:class:`IndexError` if a removal reason of a specific - number does not exist. + Both negative indices and slices can be used to interact with the removal + reasons. + + :raises: :py:class:`IndexError` if a removal reason of a specific number does + not exist. For example, to get the second removal reason of the subreddit ``"NAME"``: @@ -183,8 +188,8 @@ async def get_reason( for reason in reasons: print(reason) - If you don't need the object fetched right away (e.g., to utilize a - class method) you can do: + If you don't need the object fetched right away (e.g., to utilize a class + method) you can do: .. code-block:: python @@ -215,8 +220,7 @@ def __init__(self, subreddit: "asyncpraw.models.Subreddit"): async def __aiter__(self) -> AsyncIterator[RemovalReason]: """Return a list of Removal Reasons for the subreddit. - This method is used to discover all removal reasons for a - subreddit: + This method is used to discover all removal reasons for a subreddit: .. code-block:: python @@ -232,6 +236,7 @@ async def _removal_reason_list(self) -> List[RemovalReason]: """Get a list of Removal Reason objects. :returns: A list of instances of :class:`.RemovalReason`. + """ response = await self._reddit.get( API_PATH["removal_reasons_list"].format(subreddit=self.subreddit) @@ -246,6 +251,7 @@ async def add(self, message: str, title: str) -> RemovalReason: :param message: The message associated with the removal reason. :param title: The title of the removal reason + :returns: The RemovalReason added. The message will be prepended with `Hi u/username,` automatically. diff --git a/asyncpraw/models/reddit/rules.py b/asyncpraw/models/reddit/rules.py index 2766e1bad..39304e8d9 100644 --- a/asyncpraw/models/reddit/rules.py +++ b/asyncpraw/models/reddit/rules.py @@ -17,31 +17,27 @@ class Rule(RedditBase): **Typical Attributes** - This table describes attributes that typically belong to objects of this - class. Since attributes are dynamically provided (see - :ref:`determine-available-attributes-of-an-object`), there is not a - guarantee that these attributes will always be present, nor is this list - necessarily comprehensive. - - ======================= =================================================== - Attribute Description - ======================= =================================================== - ``created_utc`` Time the rule was created, represented in - `Unix Time`_. - ``description`` The description of the rule, if provided, otherwise - a blank string. - ``kind`` The kind of rule. Can be ``"link"``, ``comment"``, - or ``"all"``. - ``priority`` Represents where the rule is ranked. For example, - the first rule is at priority ``0``. Serves as an - index number on the list of rules. - ``short_name`` The name of the rule. - ``violation_reason`` The reason that is displayed on the report menu for - the rule. - ======================= =================================================== - - - .. _Unix Time: https://en.wikipedia.org/wiki/Unix_time + This table describes attributes that typically belong to objects of this class. + Since attributes are dynamically provided (see + :ref:`determine-available-attributes-of-an-object`), there is not a guarantee that + these attributes will always be present, nor is this list necessarily comprehensive. + + ==================== ============================================================= + Attribute Description + ==================== ============================================================= + ``created_utc`` Time the rule was created, represented in `Unix Time`_. + ``description`` The description of the rule, if provided, otherwise a blank + string. + ``kind`` The kind of rule. Can be ``"link"``, ``comment"``, or + ``"all"``. + ``priority`` Represents where the rule is ranked. For example, the first + rule is at priority ``0``. Serves as an index number on the + list of rules. + ``short_name`` The name of the rule. + ``violation_reason`` The reason that is displayed on the report menu for the rule. + ==================== ============================================================= + + .. _unix time: https://en.wikipedia.org/wiki/Unix_time """ @@ -119,17 +115,16 @@ class SubredditRules: async for rule in subreddit.rules: print(rule) - Moderators can also add rules to the subreddit. For example, to make - a rule called ``"No spam"`` in the subreddit ``"NAME"``: + Moderators can also add rules to the subreddit. For example, to make a rule called + ``"No spam"`` in the subreddit ``"NAME"``: .. code-block:: python subreddit = await reddit.subreddit("NAME") await subreddit.rules.mod.add( - short_name="No spam", - kind="all", - description="Do not spam. Spam bad" + short_name="No spam", kind="all", description="Do not spam. Spam bad" ) + """ @cachedproperty @@ -142,14 +137,11 @@ def mod(self) -> "SubredditRulesModeration": subreddit = await reddit.subreddit("NAME") await subreddit.rules.mod.add( - short_name="No spam", - kind="all", - description="Do not spam. Spam bad" + short_name="No spam", kind="all", description="Do not spam. Spam bad" ) - To move the fourth rule to the first position, and then to move the - prior first rule to where the third rule originally was in the - subreddit ``"NAME"``: + To move the fourth rule to the first position, and then to move the prior first + rule to where the third rule originally was in the subreddit ``"NAME"``: .. code-block:: python @@ -169,14 +161,15 @@ async def __call__(self) -> List["asyncpraw.models.Rule"]: .. deprecated:: 7.1 - Use the iterator by removing the call to :class:`.SubredditRules`. - For example, in order to use the iterator: + Use the iterator by removing the call to :class:`.SubredditRules`. For + example, in order to use the iterator: .. code-block:: python subreddit = await reddit.subreddit("test") async for rule in subreddit.rules: print(rule) + """ warn( "Calling SubredditRules to get a list of rules is deprecated. Remove the" @@ -208,15 +201,16 @@ async def get_rule( You can also fetch a numbered rule of a subreddit. - Rule numbers start at ``0``, so the first rule is at index ``0``, and the - second rule is at index ``1``, and so on. + Rule numbers start at ``0``, so the first rule is at index ``0``, and the second + rule is at index ``1``, and so on. + + :raises: :py:class:`IndexError` if a rule of a specific number does not exist. - :raises: :py:class:`IndexError` if a rule of a specific number does not - exist. + .. note:: - .. note:: You can use negative indexes, such as ``-1``, to get the last - rule. You can also use slices, to get a subset of rules, such as - the last three rules with ``get_rule(slice(-3, None))``. + You can use negative indexes, such as ``-1``, to get the last rule. You can + also use slices, to get a subset of rules, such as the last three rules with + ``get_rule(slice(-3, None))``. For example, to fetch the second rule of ``AskReddit``: @@ -266,6 +260,7 @@ async def _rule_list(self) -> List[Rule]: """Get a list of Rule objects. :returns: A list of instances of :class:`.Rule`. + """ rule_list = await self._reddit.get( API_PATH["rules"].format(subreddit=self.subreddit) @@ -327,13 +322,16 @@ async def update( ) -> "asyncpraw.models.Rule": """Update the rule from this subreddit. - .. note:: Existing values will be used for any unspecified arguments. + .. note:: + + Existing values will be used for any unspecified arguments. :param description: The new description for the rule. Can be empty. - :param kind: The kind of item that the rule applies to. One of - ``"link"``, ``"comment"``, or ``"all"``. + :param kind: The kind of item that the rule applies to. One of ``"link"``, + ``"comment"``, or ``"all"``. :param short_name: The name of the rule. :param violation_reason: The reason that is shown on the report menu. + :returns: A Rule object containing the updated values. To update ``"No spam"`` from the subreddit ``"NAME"`` try: @@ -373,14 +371,11 @@ class SubredditRulesModeration: subreddit = await reddit.subreddit("NAME") await subreddit.rules.mod.add( - short_name="No spam", - kind="all", - description="Do not spam. Spam bad" + short_name="No spam", kind="all", description="Do not spam. Spam bad" ) - To move the fourth rule to the first position, and then to move the prior - first rule to where the third rule originally was in the subreddit - ``"NAME"``: + To move the fourth rule to the first position, and then to move the prior first rule + to where the third rule originally was in the subreddit ``"NAME"``: .. code-block:: python @@ -406,12 +401,13 @@ async def add( """Add a removal reason to this subreddit. :param short_name: The name of the rule. - :param kind: The kind of item that the rule applies to. One of - ``"link"``, ``"comment"``, or ``"all"``. + :param kind: The kind of item that the rule applies to. One of ``"link"``, + ``"comment"``, or ``"all"``. :param description: The description for the rule. Optional. - :param violation_reason: The reason that is shown on the report menu. - If a violation reason is not specified, the short name will be used - as the violation reason. + :param violation_reason: The reason that is shown on the report menu. If a + violation reason is not specified, the short name will be used as the + violation reason. + :returns: The Rule added. To add rule ``"No spam"`` to the subreddit ``"NAME"`` try: @@ -420,9 +416,7 @@ async def add( subreddit = await reddit.subreddit("NAME") await subreddit.rules.mod.add( - short_name="No spam", - kind="all", - description="Do not spam. Spam bad" + short_name="No spam", kind="all", description="Do not spam. Spam bad" ) """ @@ -447,13 +441,14 @@ async def reorder( ) -> List["asyncpraw.models.Rule"]: """Reorder the rules of a subreddit. - :param rule_list: The list of rules, in the wanted order. Each index of - the list indicates the position of the rule. + :param rule_list: The list of rules, in the wanted order. Each index of the list + indicates the position of the rule. + :returns: A list containing the rules in the specified order. - For example, to move the fourth rule to the first position, and then to - move the prior first rule to where the third rule originally was in the - subreddit ``"NAME"``: + For example, to move the fourth rule to the first position, and then to move the + prior first rule to where the third rule originally was in the subreddit + ``"NAME"``: .. code-block:: python diff --git a/asyncpraw/models/reddit/submission.py b/asyncpraw/models/reddit/submission.py index a88c3443e..7b304932e 100644 --- a/asyncpraw/models/reddit/submission.py +++ b/asyncpraw/models/reddit/submission.py @@ -55,19 +55,17 @@ async def select(self, flair_template_id: str, text: Optional[str] = None): """Select flair for submission. :param flair_template_id: The flair template to select. The possible - ``flair_template_id`` values can be discovered through - :meth:`.choices`. - :param text: If the template's ``flair_text_editable`` value is True, - this value will set a custom text (default: None). + ``flair_template_id`` values can be discovered through :meth:`.choices`. + :param text: If the template's ``flair_text_editable`` value is True, this value + will set a custom text (default: None). - For example, to select an arbitrary editable flair text (assuming there - is one) and set a custom value try: + For example, to select an arbitrary editable flair text (assuming there is one) + and set a custom value try: .. code-block:: python choices = await submission.flair.choices() - template_id = next(x for x in choices - if x["flair_text_editable"])["flair_template_id"] + template_id = next(x for x in choices if x["flair_text_editable"])["flair_template_id"] await submission.flair.select(template_id, "my custom value") """ @@ -107,17 +105,16 @@ def __init__(self, submission: "asyncpraw.models.Submission"): async def contest_mode(self, state: bool = True): """Set contest mode for the comments of this submission. - :param state: (boolean) True enables contest mode, False, disables - (default: True). + :param state: (boolean) True enables contest mode, False, disables (default: + True). Contest mode have the following effects: - * The comment thread will default to being sorted randomly. - * Replies to top-level comments will be hidden behind "[show replies]" - buttons. - * Scores will be hidden from non-moderators. - * Scores accessed through the API (mobile apps, bots) will be obscured to - "1" for non-moderators. + - The comment thread will default to being sorted randomly. + - Replies to top-level comments will be hidden behind "[show replies]" buttons. + - Scores will be hidden from non-moderators. + - Scores accessed through the API (mobile apps, bots) will be obscured to "1" + for non-moderators. Example usage: @@ -144,8 +141,8 @@ async def flair( :param css_class: The css class to associate with the flair html (default: ""). :param flair_template_id: The flair template id to use when flairing (Optional). - This method can only be used by an authenticated user who is a - moderator of the Submission's Subreddit. + This method can only be used by an authenticated user who is a moderator of the + Submission's Subreddit. Example usage: @@ -171,8 +168,8 @@ async def flair( async def nsfw(self): """Mark as not safe for work. - This method can be used both by the submission author and moderators of - the subreddit that the submission belongs to. + This method can be used both by the submission author and moderators of the + subreddit that the submission belongs to. Example usage: @@ -184,7 +181,7 @@ async def nsfw(self): .. seealso:: - :meth:`~.sfw` + :meth:`~.sfw` """ await self.thing._reddit.post( @@ -194,10 +191,9 @@ async def nsfw(self): async def set_original_content(self): """Mark as original content. - This method can be used by moderators of the subreddit that the - submission belongs to. If the subreddit has enabled the Original - Content beta feature in settings, then the submission's author - can use it as well. + This method can be used by moderators of the subreddit that the submission + belongs to. If the subreddit has enabled the Original Content beta feature in + settings, then the submission's author can use it as well. Example usage: @@ -209,7 +205,7 @@ async def set_original_content(self): .. seealso:: - :meth:`.unset_original_content` + :meth:`.unset_original_content` """ data = { @@ -224,8 +220,8 @@ async def set_original_content(self): async def sfw(self): """Mark as safe for work. - This method can be used both by the submission author and moderators of - the subreddit that the submission belongs to. + This method can be used both by the submission author and moderators of the + subreddit that the submission belongs to. Example usage: @@ -246,8 +242,8 @@ async def sfw(self): async def spoiler(self): """Indicate that the submission contains spoilers. - This method can be used both by the submission author and moderators of - the subreddit that the submission belongs to. + This method can be used both by the submission author and moderators of the + subreddit that the submission belongs to. Example usage: @@ -268,18 +264,19 @@ async def spoiler(self): async def sticky(self, state: bool = True, bottom: bool = True): """Set the submission's sticky state in its subreddit. - :param state: (boolean) True sets the sticky for the submission, false - unsets (default: True). - :param bottom: (boolean) When true, set the submission as the bottom - sticky. If no top sticky exists, this submission will become the - top sticky regardless (default: True). + :param state: (boolean) True sets the sticky for the submission, false unsets + (default: True). + :param bottom: (boolean) When true, set the submission as the bottom sticky. If + no top sticky exists, this submission will become the top sticky regardless + (default: True). + + .. note:: - .. note:: When a submission is stickied two or more times, the Reddit - API responds with a 409 error that is raises as a ``Conflict`` by - asyncprawcore. The method suppresses these ``Conflict`` errors. + When a submission is stickied two or more times, the Reddit API responds + with a 409 error that is raises as a ``Conflict`` by asyncprawcore. The + method suppresses these ``Conflict`` errors. - This submission will replace the second stickied submission if one - exists. + This submission will replace the second stickied submission if one exists. For example: @@ -302,8 +299,8 @@ async def sticky(self, state: bool = True, bottom: bool = True): async def suggested_sort(self, sort: str = "blank"): """Set the suggested sort for the comments of the submission. - :param sort: Can be one of: confidence, top, new, controversial, old, - random, qa, blank (default: blank). + :param sort: Can be one of: confidence, top, new, controversial, old, random, + qa, blank (default: blank). """ await self.thing._reddit.post( @@ -314,10 +311,9 @@ async def suggested_sort(self, sort: str = "blank"): async def unset_original_content(self): """Indicate that the submission is not original content. - This method can be used by moderators of the subreddit that the - submission belongs to. If the subreddit has enabled the Original - Content beta feature in settings, then the submission's author - can use it as well. + This method can be used by moderators of the subreddit that the submission + belongs to. If the subreddit has enabled the Original Content beta feature in + settings, then the submission's author can use it as well. Example usage: @@ -344,8 +340,8 @@ async def unset_original_content(self): async def unspoiler(self): """Indicate that the submission does not contain spoilers. - This method can be used both by the submission author and moderators of - the subreddit that the submission belongs to. + This method can be used both by the submission author and moderators of the + subreddit that the submission belongs to. For example: @@ -370,58 +366,51 @@ class Submission(SubmissionListingMixin, UserContentMixin, FullnameMixin, Reddit **Typical Attributes** - This table describes attributes that typically belong to objects of this - class. Since attributes are dynamically provided (see - :ref:`determine-available-attributes-of-an-object`), there is not a - guarantee that these attributes will always be present, nor is this list - necessarily complete. - - =========================== =============================================== - Attribute Description - =========================== =============================================== - ``author`` Provides an instance of :class:`.Redditor`. - ``clicked`` Whether or not the submission has been clicked - by the client. - ``comments`` Provides an instance of - :class:`.CommentForest`. - ``created_utc`` Time the submission was created, represented in - `Unix Time`_. - ``distinguished`` Whether or not the submission is distinguished. - ``edited`` Whether or not the submission has been edited. - ``id`` ID of the submission. - ``is_original_content`` Whether or not the submission has been set - as original content. - ``is_self`` Whether or not the submission is a selfpost - (text-only). - ``link_flair_template_id`` The link flair's ID, or None if not flaired. - ``link_flair_text`` The link flair's text content, or None if not - flaired. - ``locked`` Whether or not the submission has been locked. - ``name`` Fullname of the submission. - ``num_comments`` The number of comments on the submission. - ``over_18`` Whether or not the submission has been marked - as NSFW. - ``permalink`` A permalink for the submission. - ``poll_data`` A :class:`.PollData` object representing the - data of this submission, if it is a poll - submission. - ``saved`` Whether or not the submission is saved. - ``score`` The number of upvotes for the submission. - ``selftext`` The submissions' selftext - an empty string if - a link post. - ``spoiler`` Whether or not the submission has been marked - as a spoiler. - ``stickied`` Whether or not the submission is stickied. - ``subreddit`` Provides an instance of :class:`.Subreddit`. - ``title`` The title of the submission. - ``upvote_ratio`` The percentage of upvotes from all votes on the - submission. - ``url`` The URL the submission links to, or the - permalink if a selfpost. - =========================== =============================================== - - - .. _Unix Time: https://en.wikipedia.org/wiki/Unix_time + This table describes attributes that typically belong to objects of this class. + Since attributes are dynamically provided (see + :ref:`determine-available-attributes-of-an-object`), there is not a guarantee that + these attributes will always be present, nor is this list necessarily complete. + + ========================== ========================================================= + Attribute Description + ========================== ========================================================= + ``author`` Provides an instance of :class:`.Redditor`. + ``clicked`` Whether or not the submission has been clicked by the + client. + ``comments`` Provides an instance of :class:`.CommentForest`. + ``created_utc`` Time the submission was created, represented in `Unix + Time`_. + ``distinguished`` Whether or not the submission is distinguished. + ``edited`` Whether or not the submission has been edited. + ``id`` ID of the submission. + ``is_original_content`` Whether or not the submission has been set as original + content. + ``is_self`` Whether or not the submission is a selfpost (text-only). + ``link_flair_template_id`` The link flair's ID, or None if not flaired. + ``link_flair_text`` The link flair's text content, or None if not flaired. + ``locked`` Whether or not the submission has been locked. + ``name`` Fullname of the submission. + ``num_comments`` The number of comments on the submission. + ``over_18`` Whether or not the submission has been marked as NSFW. + ``permalink`` A permalink for the submission. + ``poll_data`` A :class:`.PollData` object representing the data of this + submission, if it is a poll submission. + ``saved`` Whether or not the submission is saved. + ``score`` The number of upvotes for the submission. + ``selftext`` The submissions' selftext - an empty string if a link + post. + ``spoiler`` Whether or not the submission has been marked as a + spoiler. + ``stickied`` Whether or not the submission is stickied. + ``subreddit`` Provides an instance of :class:`.Subreddit`. + ``title`` The title of the submission. + ``upvote_ratio`` The percentage of upvotes from all votes on the + submission. + ``url`` The URL the submission links to, or the permalink if a + selfpost. + ========================== ========================================================= + + .. _unix time: https://en.wikipedia.org/wiki/Unix_time """ @@ -431,13 +420,13 @@ class Submission(SubmissionListingMixin, UserContentMixin, FullnameMixin, Reddit def id_from_url(url: str) -> str: """Return the ID contained within a submission URL. - :param url: A url to a submission in one of the following formats (http - urls will also work): + :param url: A url to a submission in one of the following formats (http urls + will also work): - * https://redd.it/2gmzqe - * https://reddit.com/comments/2gmzqe/ - * https://www.reddit.com/r/redditdev/comments/2gmzqe/praw_https/ - * https://www.reddit.com/gallery/2gmzqe + - https://redd.it/2gmzqe + - https://reddit.com/comments/2gmzqe/ + - https://www.reddit.com/r/redditdev/comments/2gmzqe/praw_https/ + - https://www.reddit.com/gallery/2gmzqe :raises: :class:`.InvalidURL` if URL is not a valid submission URL. @@ -471,8 +460,8 @@ def _kind(self) -> str: async def comments(self) -> CommentForest: """Provide an instance of :class:`.CommentForest`. - This attribute can be used, for example, to obtain a flat list of - comments, with any :class:`.MoreComments` removed: + This attribute can be used, for example, to obtain a flat list of comments, with + any :class:`.MoreComments` removed: .. code-block:: python @@ -484,8 +473,8 @@ async def comments(self) -> CommentForest: ... Sort order and comment limit can be set with the ``comment_sort`` and - ``comment_limit`` attributes before comments are fetched, including - any call to :meth:`.replace_more`: + ``comment_limit`` attributes before comments are fetched, including any call to + :meth:`.replace_more`: .. code-block:: python @@ -496,9 +485,10 @@ async def comments(self) -> CommentForest: # do stuff with comment ... - .. note:: The appropriate values for ``comment_sort`` include - ``confidence``, ``controversial``, ``new``, ``old``, ``q&a``, - and ``top`` + .. note:: + + The appropriate values for ``comment_sort`` include ``confidence``, + ``controversial``, ``new``, ``old``, ``q&a``, and ``top`` See :ref:`extracting_comments` for more on working with a :class:`.CommentForest`. @@ -513,12 +503,11 @@ async def comments(self) -> CommentForest: def flair(self) -> SubmissionFlair: """Provide an instance of :class:`.SubmissionFlair`. - This attribute is used to work with flair as a regular user of the - subreddit the submission belongs to. Moderators can directly use - :meth:`.flair`. + This attribute is used to work with flair as a regular user of the subreddit the + submission belongs to. Moderators can directly use :meth:`.flair`. - For example, to select an arbitrary editable flair text (assuming there - is one) and set a custom value try: + For example, to select an arbitrary editable flair text (assuming there is one) + and set a custom value try: .. code-block:: python @@ -564,8 +553,7 @@ def __init__( :param reddit: An instance of :class:`~.Reddit`. :param id: A reddit base36 submission ID, e.g., ``2gmzqe``. - :param url: A URL supported by - :meth:`~asyncpraw.models.Submission.id_from_url`. + :param url: A URL supported by :meth:`~asyncpraw.models.Submission.id_from_url`. Either ``id`` or ``url`` can be provided, but not both. @@ -653,9 +641,8 @@ async def hide( ): """Hide Submission. - :param other_submissions: When provided, additionally - hide this list of :class:`.Submission` instances - as part of a single request (default: None). + :param other_submissions: When provided, additionally hide this list of + :class:`.Submission` instances as part of a single request (default: None). Example usage: @@ -677,9 +664,8 @@ async def unhide( ): """Unhide Submission. - :param other_submissions: When provided, additionally - unhide this list of :class:`.Submission` instances - as part of a single request (default: None). + :param other_submissions: When provided, additionally unhide this list of + :class:`.Submission` instances as part of a single request (default: None). Example usage: @@ -709,32 +695,33 @@ async def crosspost( """Crosspost the submission to a subreddit. .. note:: + Be aware you have to be subscribed to the target subreddit. - :param subreddit: Name of the subreddit or :class:`~.Subreddit` - object to crosspost into. - :param title: Title of the submission. Will use this submission's - title if `None` (default: None). + :param subreddit: Name of the subreddit or :class:`~.Subreddit` object to + crosspost into. + :param title: Title of the submission. Will use this submission's title if + `None` (default: None). :param flair_id: The flair template to select (default: None). - :param flair_text: If the template's ``flair_text_editable`` value is - True, this value will set a custom text (default: None). - :param send_replies: When True, messages will be sent to the - submission author when comments are made to the submission - (default: True). - :param nsfw: Whether or not the submission should be marked NSFW + :param flair_text: If the template's ``flair_text_editable`` value is True, this + value will set a custom text (default: None). + :param send_replies: When True, messages will be sent to the submission author + when comments are made to the submission (default: True). + :param nsfw: Whether or not the submission should be marked NSFW (default: + False). + :param spoiler: Whether or not the submission should be marked as a spoiler (default: False). - :param spoiler: Whether or not the submission should be marked as - a spoiler (default: False). - :returns: A :class:`~.Submission` object for the newly created - submission. + + :returns: A :class:`~.Submission` object for the newly created submission. Example usage: .. code-block:: python submission = await reddit.submission(id="5or86n") - cross_post = await submission.crosspost(subreddit="learnprogramming", - send_replies=False) + cross_post = await submission.crosspost( + subreddit="learnprogramming", send_replies=False + ) .. seealso:: diff --git a/asyncpraw/models/reddit/subreddit.py b/asyncpraw/models/reddit/subreddit.py index 8ffaf511c..941d43857 100644 --- a/asyncpraw/models/reddit/subreddit.py +++ b/asyncpraw/models/reddit/subreddit.py @@ -66,9 +66,8 @@ class Subreddit(MessageableMixin, SubredditListingMixin, FullnameMixin, RedditBa subreddit = await reddit.subreddit("redditdev") - While ``r/all`` is not a real subreddit, it can still be treated like - one. The following outputs the titles of the 25 hottest submissions in - ``r/all``: + While ``r/all`` is not a real subreddit, it can still be treated like one. The + following outputs the titles of the 25 hottest submissions in ``r/all``: .. code-block:: python @@ -88,8 +87,8 @@ class Subreddit(MessageableMixin, SubredditListingMixin, FullnameMixin, RedditBa .. note:: - These filters are ignored by certain methods, including :attr:`.comments`, :meth:`.gilded`, - and :meth:`.SubredditStream.comments`. + These filters are ignored by certain methods, including :attr:`.comments`, + :meth:`.gilded`, and :meth:`.SubredditStream.comments`. .. code-block:: python @@ -99,40 +98,41 @@ class Subreddit(MessageableMixin, SubredditListingMixin, FullnameMixin, RedditBa **Typical Attributes** - This table describes attributes that typically belong to objects of this - class. Since attributes are dynamically provided (see - :ref:`determine-available-attributes-of-an-object`), there is not a - guarantee that these attributes will always be present, nor is this list - necessarily complete. - - ========================== =============================================== - Attribute Description - ========================== =============================================== - ``can_assign_link_flair`` Whether users can assign their own link flair. - ``can_assign_user_flair`` Whether users can assign their own user flair. - ``created_utc`` Time the subreddit was created, represented in - `Unix Time`_. - ``description`` Subreddit description, in Markdown. - ``description_html`` Subreddit description, in HTML. - ``display_name`` Name of the subreddit. - ``id`` ID of the subreddit. - ``name`` Fullname of the subreddit. - ``over18`` Whether the subreddit is NSFW. - ``public_description`` Description of the subreddit, shown in searches - and on the "You must be invited to visit this - community" page (if applicable). - ``spoilers_enabled`` Whether the spoiler tag feature is enabled. - ``subscribers`` Count of subscribers. - ``user_is_banned`` Whether the authenticated user is banned. - ``user_is_moderator`` Whether the authenticated user is a moderator. - ``user_is_subscriber`` Whether the authenticated user is subscribed. - ========================== =============================================== - - .. note:: Trying to retrieve attributes of quarantined or private - subreddits will result in a 403 error. Trying to retrieve attributes of - a banned subreddit will result in a 404 error. - - .. _Unix Time: https://en.wikipedia.org/wiki/Unix_time + This table describes attributes that typically belong to objects of this class. + Since attributes are dynamically provided (see + :ref:`determine-available-attributes-of-an-object`), there is not a guarantee that + these attributes will always be present, nor is this list necessarily complete. + + ========================= ========================================================== + Attribute Description + ========================= ========================================================== + ``can_assign_link_flair`` Whether users can assign their own link flair. + ``can_assign_user_flair`` Whether users can assign their own user flair. + ``created_utc`` Time the subreddit was created, represented in `Unix + Time`_. + ``description`` Subreddit description, in Markdown. + ``description_html`` Subreddit description, in HTML. + ``display_name`` Name of the subreddit. + ``id`` ID of the subreddit. + ``name`` Fullname of the subreddit. + ``over18`` Whether the subreddit is NSFW. + ``public_description`` Description of the subreddit, shown in searches and on the + "You must be invited to visit this community" page (if + applicable). + ``spoilers_enabled`` Whether the spoiler tag feature is enabled. + ``subscribers`` Count of subscribers. + ``user_is_banned`` Whether the authenticated user is banned. + ``user_is_moderator`` Whether the authenticated user is a moderator. + ``user_is_subscriber`` Whether the authenticated user is subscribed. + ========================= ========================================================== + + .. note:: + + Trying to retrieve attributes of quarantined or private subreddits will result + in a 403 error. Trying to retrieve attributes of a banned subreddit will result + in a 404 error. + + .. _unix time: https://en.wikipedia.org/wiki/Unix_time """ @@ -274,8 +274,8 @@ def banned(self) -> "asyncpraw.models.reddit.subreddit.SubredditRelationship": def collections(self) -> "asyncpraw.models.reddit.collections.SubredditCollections": r"""Provide an instance of :class:`.SubredditCollections`. - To see the permalinks of all :class:`.Collection`\ s that belong to - a subreddit, try: + To see the permalinks of all :class:`.Collection`\ s that belong to a subreddit, + try: .. code-block:: python @@ -283,15 +283,17 @@ def collections(self) -> "asyncpraw.models.reddit.collections.SubredditCollectio async for collection in subreddit.collections: print(collection.permalink) - To get a specific :class:`.Collection` by its UUID or permalink, - use one of the following: + To get a specific :class:`.Collection` by its UUID or permalink, use one of the + following: .. code-block:: python subreddit = await reddit.subreddit("SUBREDDIT") collection = subreddit.collections("some_uuid") - collection = subreddit.collections(permalink="https://reddit.com/r/SUBREDDIT/collection/some_uuid") + collection = subreddit.collections( + permalink="https://reddit.com/r/SUBREDDIT/collection/some_uuid" + ) """ return self._subreddit_collections_class(self._reddit, self) @@ -333,8 +335,10 @@ def emoji(self) -> SubredditEmoji: subreddit = await reddit.subreddit("blah") emoji = await subreddit.emoji.get_emoji("emoji_name") - .. note:: Attempting to access attributes of an nonexistent emoji will - result in a :class:`.ClientException`. + .. note:: + + Attempting to access attributes of an nonexistent emoji will result in a + :class:`.ClientException`. """ return SubredditEmoji(self) @@ -357,9 +361,9 @@ def filters(self) -> "asyncpraw.models.reddit.subreddit.SubredditFilters": def flair(self) -> "asyncpraw.models.reddit.subreddit.SubredditFlair": """Provide an instance of :class:`.SubredditFlair`. - Use this attribute for interacting with a subreddit's flair. For - example, to list all the flair for a subreddit which you have the - ``flair`` moderator permission on try: + Use this attribute for interacting with a subreddit's flair. For example, to + list all the flair for a subreddit which you have the ``flair`` moderator + permission on try: .. code-block:: python @@ -418,9 +422,8 @@ def moderator(self) -> "asyncpraw.models.reddit.subreddit.ModeratorRelationship" def modmail(self) -> "asyncpraw.models.reddit.subreddit.Modmail": """Provide an instance of :class:`.Modmail`. - For example, to send a new modmail from the subreddit ``r/test`` to - user ``u/spez`` with the subject ``test`` along with a message body of - ``hello``: + For example, to send a new modmail from the subreddit ``r/test`` to user + ``u/spez`` with the subject ``test`` along with a message body of ``hello``: .. code-block:: python @@ -449,9 +452,9 @@ def muted(self) -> "asyncpraw.models.reddit.subreddit.SubredditRelationship": def quaran(self) -> "asyncpraw.models.reddit.subreddit.SubredditQuarantine": """Provide an instance of :class:`.SubredditQuarantine`. - This property is named ``quaran`` because ``quarantine`` is a - Subreddit attribute returned by Reddit to indicate whether or not a - Subreddit is quarantined. + This property is named ``quaran`` because ``quarantine`` is a Subreddit + attribute returned by Reddit to indicate whether or not a Subreddit is + quarantined. To opt-in into a quarantined subreddit: @@ -477,16 +480,15 @@ def rules(self) -> SubredditRules: async for rule in subreddit.rules: print(rule) - Moderators can also add rules to the subreddit. For example, to make - a rule called ``"No spam"`` in the subreddit ``"NAME"``: + Moderators can also add rules to the subreddit. For example, to make a rule + called ``"No spam"`` in the subreddit ``"NAME"``: .. code-block:: python subreddit = await reddit.subreddit("NAME") await subreddit.rules.mod.add( - short_name="No spam", - kind="all", - description="Do not spam. Spam bad") + short_name="No spam", kind="all", description="Do not spam. Spam bad" + ) """ return SubredditRules(self) @@ -495,8 +497,8 @@ def rules(self) -> SubredditRules: def stream(self) -> "asyncpraw.models.reddit.subreddit.SubredditStream": """Provide an instance of :class:`.SubredditStream`. - Streams can be used to indefinitely retrieve new comments made to a - subreddit, like: + Streams can be used to indefinitely retrieve new comments made to a subreddit, + like: .. code-block:: python @@ -504,9 +506,8 @@ def stream(self) -> "asyncpraw.models.reddit.subreddit.SubredditStream": async for comment in subreddit.stream.comments(): print(comment) - Additionally, new submissions can be retrieved via the stream. In the - following example all submissions are fetched via the special subreddit - ``r/all``: + Additionally, new submissions can be retrieved via the stream. In the following + example all submissions are fetched via the special subreddit ``r/all``: .. code-block:: python @@ -593,8 +594,10 @@ def __init__( :param reddit: An instance of :class:`~.Reddit`. :param display_name: The name of the subreddit. - .. note:: This class should not be initialized directly. Instead obtain - an instance via: + .. note:: + + This class should not be initialized directly. Instead obtain an instance + via: .. code-block:: python @@ -616,6 +619,7 @@ async def _convert_to_fancypants(self, markdown_text: str) -> dict: """Convert a Markdown string to a dict for use with the ``richtext_json`` param. :param markdown_text: A Markdown string to convert. + :returns: A dict in ``richtext_json`` format. """ @@ -651,8 +655,9 @@ def _parse_xml_response(self, response: Response): async def _submit_media(self, data: dict, timeout: int, websocket_url: str = None): """Submit and return an `image`, `video`, or `videogif`. - This is a helper method for submitting posts that are not link posts or - self posts. + This is a helper method for submitting posts that are not link posts or self + posts. + """ if websocket_url is None: await self._reddit.post(API_PATH["submit"], data=data) @@ -698,14 +703,14 @@ async def _upload_media( ): """Upload media and return its URL and a websocket (Undocumented endpoint). - :param expected_mime_prefix: If provided, enforce that the media has a - mime type that starts with the provided prefix. + :param expected_mime_prefix: If provided, enforce that the media has a mime type + that starts with the provided prefix. :param upload_type: One of ``link``, ``gallery'', or ``selfpost``. (default: ``link``) - :returns: A tuple containing ``(media_url, websocket_url)`` for the - piece of media. The websocket URL can be used to determine when - media processing is finished, or it can be ignored. + :returns: A tuple containing ``(media_url, websocket_url)`` for the piece of + media. The websocket URL can be used to determine when media processing is + finished, or it can be ignored. """ if media_path is None: @@ -777,24 +782,24 @@ async def post_requirements(self) -> Dict[str, Union[str, int, bool]]: The returned dict contains the following keys: - * ``domain_blacklist`` - * ``body_restriction_policy`` - * ``domain_whitelist`` - * ``title_regexes`` - * ``body_blacklisted_strings`` - * ``body_required_strings`` - * ``title_text_min_length`` - * ``is_flair_required`` - * ``title_text_max_length`` - * ``body_regexes`` - * ``link_repost_age`` - * ``body_text_min_length`` - * ``link_restriction_policy`` - * ``body_text_max_length`` - * ``title_required_strings`` - * ``title_blacklisted_strings`` - * ``guidelines_text`` - * ``guidelines_display_policy`` + - ``domain_blacklist`` + - ``body_restriction_policy`` + - ``domain_whitelist`` + - ``title_regexes`` + - ``body_blacklisted_strings`` + - ``body_required_strings`` + - ``title_text_min_length`` + - ``is_flair_required`` + - ``title_text_max_length`` + - ``body_regexes`` + - ``link_repost_age`` + - ``body_text_min_length`` + - ``link_restriction_policy`` + - ``body_text_max_length`` + - ``title_required_strings`` + - ``title_blacklisted_strings`` + - ``guidelines_text`` + - ``guidelines_display_policy`` For example, to fetch the post requirements for ``r/test``: @@ -812,8 +817,8 @@ async def post_requirements(self) -> Dict[str, Union[str, int, bool]]: async def random(self) -> Union["asyncpraw.models.Submission", None]: """Return a random Submission. - Returns ``None`` on subreddits that do not support the random feature. - One example, at the time of writing, is ``r/wallpapers``. + Returns ``None`` on subreddits that do not support the random feature. One + example, at the time of writing, is ``r/wallpapers``. For example, to get a random submission off of ``r/AskReddit``: @@ -849,12 +854,11 @@ def search( """Return a :class:`.ListingGenerator` for items that match ``query``. :param query: The query string to search for. - :param sort: Can be one of: relevance, hot, top, new, - comments. (default: relevance). - :param syntax: Can be one of: cloudsearch, lucene, plain - (default: lucene). - :param time_filter: Can be one of: all, day, hour, month, week, year - (default: all). + :param sort: Can be one of: relevance, hot, top, new, comments. (default: + relevance). + :param syntax: Can be one of: cloudsearch, lucene, plain (default: lucene). + :param time_filter: Can be one of: all, day, hour, month, week, year (default: + all). For more information on building a search query see: https://www.reddit.com/wiki/search @@ -885,8 +889,8 @@ def search( async def sticky(self, number: int = 1) -> "asyncpraw.models.Submission": """Return a Submission object for a sticky of the subreddit. - :param number: Specify which sticky to return. 1 appears at the top - (default: 1). + :param number: Specify which sticky to return. 1 appears at the top (default: + 1). :raises: ``asyncprawcore.NotFound`` if the sticky does not exist. @@ -927,30 +931,29 @@ async def submit( r"""Add a submission to the subreddit. :param title: The title of the submission. - :param selftext: The Markdown formatted content for a ``text`` - submission. Use an empty string, ``""``, to make a title-only - submission. + :param selftext: The Markdown formatted content for a ``text`` submission. Use + an empty string, ``""``, to make a title-only submission. :param url: The URL for a ``link`` submission. :param collection_id: The UUID of a :class:`.Collection` to add the newly-submitted post to. :param flair_id: The flair template to select (default: None). - :param flair_text: If the template's ``flair_text_editable`` value is - True, this value will set a custom text (default: None). ``flair_id`` is - required when ``flair_text`` is provided. - :param resubmit: When False, an error will occur if the URL has already - been submitted (default: True). - :param send_replies: When True, messages will be sent to the submission - author when comments are made to the submission (default: True). - :param nsfw: Whether or not the submission should be marked NSFW + :param flair_text: If the template's ``flair_text_editable`` value is True, this + value will set a custom text (default: None). ``flair_id`` is required when + ``flair_text`` is provided. + :param resubmit: When False, an error will occur if the URL has already been + submitted (default: True). + :param send_replies: When True, messages will be sent to the submission author + when comments are made to the submission (default: True). + :param nsfw: Whether or not the submission should be marked NSFW (default: + False). + :param spoiler: Whether or not the submission should be marked as a spoiler (default: False). - :param spoiler: Whether or not the submission should be marked as - a spoiler (default: False). - :param discussion_type: Set to ``CHAT`` to enable live discussion - instead of traditional comments (default: None). + :param discussion_type: Set to ``CHAT`` to enable live discussion instead of + traditional comments (default: None). :param inline_media: A dict of :class:`.InlineMedia` objects where the key is the placeholder name in ``selftext``. - :returns: A :class:`~.Submission` object for the newly created - submission. + + :returns: A :class:`~.Submission` object for the newly created submission. Either ``selftext`` or ``url`` can be provided, but not both. @@ -973,9 +976,9 @@ async def submit( image = InlineImage("path/to/image.jpg", "optional caption") video = InlineVideo("path/to/video.mp4", "optional caption") selftext = "Text with a gif {gif1} an image {image1} and a video {video1} inline" - media = {'gif1': gif, 'image1': image, 'video1': video} - subreddit = await reddit.subreddit('redditdev') - await subreddit.submit('title', selftext=selftext, inline_media=media) + media = {"gif1": gif, "image1": image, "video1": video} + subreddit = await reddit.subreddit("redditdev") + await subreddit.submit("title", selftext=selftext, inline_media=media) .. note:: @@ -999,12 +1002,12 @@ async def submit( inline - .. seealso :: + .. seealso:: - * :meth:`.submit_image` to submit images - * :meth:`.submit_video` to submit videos and videogifs - * :meth:`.submit_poll` to submit polls - * :meth:`.submit_gallery`. to submit more than one image in the same post + - :meth:`.submit_image` to submit images + - :meth:`.submit_video` to submit videos and videogifs + - :meth:`.submit_poll` to submit polls + - :meth:`.submit_gallery`. to submit more than one image in the same post """ if (bool(selftext) or selftext == "") == bool(url): @@ -1069,18 +1072,20 @@ async def submit_gallery( :param discussion_type: Set to ``CHAT`` to enable live discussion instead of traditional comments (default: None). :param flair_id: The flair template to select (default: None). - :param flair_text: If the template's ``flair_text_editable`` value is - True, this value will set a custom text (default: None). ``flair_id`` is - required when ``flair_text`` is provided. - :param nsfw: Whether or not the submission should be marked NSFW - (default: False). + :param flair_text: If the template's ``flair_text_editable`` value is True, this + value will set a custom text (default: None). ``flair_id`` is required when + ``flair_text`` is provided. + :param nsfw: Whether or not the submission should be marked NSFW (default: + False). :param send_replies: When True, messages will be sent to the submission author when comments are made to the submission (default: True). :param spoiler: Whether or not the submission should be marked asa spoiler (default: False). + :returns: A :class:`.Submission` object for the newly created submission. - :raises: :class:`.ClientException` if ``image_path`` in ``images`` refers to a file that is not an image. + :raises: :class:`.ClientException` if ``image_path`` in ``images`` refers to a + file that is not an image. For example, to submit an image gallery to ``r/reddit_api_test`` do: @@ -1091,28 +1096,26 @@ async def submit_gallery( image2 = "/path/to/image2.png" image3 = "/path/to/image3.png" images = [ - { - "image_path": image - }, - { - "image_path": image2, - "caption": "Image caption 2", - }, - { - "image_path": image3, - "caption": "Image caption 3", - "outbound_url": "https://example.com/link3" - } + {"image_path": image}, + { + "image_path": image2, + "caption": "Image caption 2", + }, + { + "image_path": image3, + "caption": "Image caption 3", + "outbound_url": "https://example.com/link3", + }, ] subreddit = await reddit.subreddit("reddit_api_test") await subreddit.submit_gallery(title, images) - .. seealso :: + .. seealso:: - * :meth:`.submit` to submit url posts and selftexts - * :meth:`.submit_image`. to submit single images - * :meth:`.submit_poll` to submit polls - * :meth:`.submit_video`. to submit videos and videogifs + - :meth:`.submit` to submit url posts and selftexts + - :meth:`.submit_image`. to submit single images + - :meth:`.submit_poll` to submit polls + - :meth:`.submit_video`. to submit videos and videogifs """ self._validate_gallery(images) @@ -1180,43 +1183,43 @@ async def submit_image( :param collection_id: The UUID of a :class:`.Collection` to add the newly-submitted post to. :param flair_id: The flair template to select (default: None). - :param flair_text: If the template's ``flair_text_editable`` value is - True, this value will set a custom text (default: None). ``flair_id`` is - required when ``flair_text`` is provided. - :param resubmit: When False, an error will occur if the URL has already - been submitted (default: True). - :param send_replies: When True, messages will be sent to the submission - author when comments are made to the submission (default: True). - :param nsfw: Whether or not the submission should be marked NSFW + :param flair_text: If the template's ``flair_text_editable`` value is True, this + value will set a custom text (default: None). ``flair_id`` is required when + ``flair_text`` is provided. + :param resubmit: When False, an error will occur if the URL has already been + submitted (default: True). + :param send_replies: When True, messages will be sent to the submission author + when comments are made to the submission (default: True). + :param nsfw: Whether or not the submission should be marked NSFW (default: + False). + :param spoiler: Whether or not the submission should be marked as a spoiler (default: False). - :param spoiler: Whether or not the submission should be marked as - a spoiler (default: False). - :param timeout: Specifies a particular timeout, in seconds. Use to - avoid "Websocket error" exceptions (default: 10). - :param without_websockets: Set to ``True`` to disable use of WebSockets - (see note below for an explanation). If ``True``, this method - doesn't return anything. (default: ``False``). - :param discussion_type: Set to ``CHAT`` to enable live discussion - instead of traditional comments (default: None). - :returns: A :class:`.Submission` object for the newly created - submission, unless ``without_websockets`` is ``True``. - - :raises: :class:`.ClientException` if ``image_path`` refers to a file that is not an image. + :param timeout: Specifies a particular timeout, in seconds. Use to avoid + "Websocket error" exceptions (default: 10). + :param without_websockets: Set to ``True`` to disable use of WebSockets (see + note below for an explanation). If ``True``, this method doesn't return + anything. (default: ``False``). + :param discussion_type: Set to ``CHAT`` to enable live discussion instead of + traditional comments (default: None). + + :returns: A :class:`.Submission` object for the newly created submission, unless + ``without_websockets`` is ``True``. + + :raises: :class:`.ClientException` if ``image_path`` refers to a file that is + not an image. .. note:: - Reddit's API uses WebSockets to respond with the link of the - newly created post. If this fails, the method will raise - :class:`.WebSocketException`. Occasionally, the Reddit post will - still be created. More often, there is an error with the image - file. If you frequently get exceptions but successfully created - posts, try setting the ``timeout`` parameter to a value above 10. + Reddit's API uses WebSockets to respond with the link of the newly created + post. If this fails, the method will raise :class:`.WebSocketException`. + Occasionally, the Reddit post will still be created. More often, there is an + error with the image file. If you frequently get exceptions but successfully + created posts, try setting the ``timeout`` parameter to a value above 10. - To disable the use of WebSockets, set ``without_websockets=True``. - This will make the method return ``None``, though the post will - still be created. You may wish to do this if you are running your - program in a restricted network environment, or using a proxy - that doesn't support WebSockets connections. + To disable the use of WebSockets, set ``without_websockets=True``. This will + make the method return ``None``, though the post will still be created. You + may wish to do this if you are running your program in a restricted network + environment, or using a proxy that doesn't support WebSockets connections. For example, to submit an image to ``r/reddit_api_test`` do: @@ -1227,11 +1230,11 @@ async def submit_image( subreddit = await reddit.subreddit("reddit_api_test") await subreddit.submit_image(title, image) - .. seealso :: + .. seealso:: - * :meth:`.submit` to submit url posts and selftexts - * :meth:`.submit_video`. to submit videos and videogifs - * :meth:`.submit_gallery`. to submit more than one image in the same post + - :meth:`.submit` to submit url posts and selftexts + - :meth:`.submit_video`. to submit videos and videogifs + - :meth:`.submit_gallery`. to submit more than one image in the same post """ data = { @@ -1282,30 +1285,29 @@ async def submit_poll( """Add a poll submission to the subreddit. :param title: The title of the submission. - :param selftext: The Markdown formatted content for the - submission. Use an empty string, ``""``, to make a submission - with no text contents. + :param selftext: The Markdown formatted content for the submission. Use an empty + string, ``""``, to make a submission with no text contents. :param options: A ``list`` of two to six poll options as ``str``. - :param duration: The number of days the poll should accept votes, - as an ``int``. Valid values are between ``1`` and ``7``, inclusive. + :param duration: The number of days the poll should accept votes, as an ``int``. + Valid values are between ``1`` and ``7``, inclusive. :param collection_id: The UUID of a :class:`.Collection` to add the newly-submitted post to. :param flair_id: The flair template to select (default: None). - :param flair_text: If the template's ``flair_text_editable`` value is - True, this value will set a custom text (default: None). ``flair_id`` is - required when ``flair_text`` is provided. - :param resubmit: When False, an error will occur if the URL has already - been submitted (default: True). - :param send_replies: When True, messages will be sent to the submission - author when comments are made to the submission (default: True). - :param nsfw: Whether or not the submission should be marked NSFW + :param flair_text: If the template's ``flair_text_editable`` value is True, this + value will set a custom text (default: None). ``flair_id`` is required when + ``flair_text`` is provided. + :param resubmit: When False, an error will occur if the URL has already been + submitted (default: True). + :param send_replies: When True, messages will be sent to the submission author + when comments are made to the submission (default: True). + :param nsfw: Whether or not the submission should be marked NSFW (default: + False). + :param spoiler: Whether or not the submission should be marked as a spoiler (default: False). - :param spoiler: Whether or not the submission should be marked as - a spoiler (default: False). - :param discussion_type: Set to ``CHAT`` to enable live discussion - instead of traditional comments (default: None). - :returns: A :class:`~.Submission` object for the newly created - submission. + :param discussion_type: Set to ``CHAT`` to enable live discussion instead of + traditional comments (default: None). + + :returns: A :class:`~.Submission` object for the newly created submission. For example, to submit a poll to ``r/reddit_api_test`` do: @@ -1360,53 +1362,51 @@ async def submit_video( :param title: The title of the submission. :param video_path: The path to a video, to upload and post. - :param videogif: A ``bool`` value. If ``True``, the video is - uploaded as a videogif, which is essentially a silent video - (default: ``False``). - :param thumbnail_path: (Optional) The path to an image, to be uploaded - and used as the thumbnail for this video. If not provided, the - PRAW logo will be used as the thumbnail. + :param videogif: A ``bool`` value. If ``True``, the video is uploaded as a + videogif, which is essentially a silent video (default: ``False``). + :param thumbnail_path: (Optional) The path to an image, to be uploaded and used + as the thumbnail for this video. If not provided, the PRAW logo will be used + as the thumbnail. :param collection_id: The UUID of a :class:`.Collection` to add the newly-submitted post to. :param flair_id: The flair template to select (default: ``None``). - :param flair_text: If the template's ``flair_text_editable`` value is - True, this value will set a custom text (default: ``None``). ``flair_id`` is - required when ``flair_text`` is provided. - :param resubmit: When False, an error will occur if the URL has already - been submitted (default: ``True``). - :param send_replies: When True, messages will be sent to the submission - author when comments are made to the submission - (default: ``True``). - :param nsfw: Whether or not the submission should be marked NSFW + :param flair_text: If the template's ``flair_text_editable`` value is True, this + value will set a custom text (default: ``None``). ``flair_id`` is required + when ``flair_text`` is provided. + :param resubmit: When False, an error will occur if the URL has already been + submitted (default: ``True``). + :param send_replies: When True, messages will be sent to the submission author + when comments are made to the submission (default: ``True``). + :param nsfw: Whether or not the submission should be marked NSFW (default: + False). + :param spoiler: Whether or not the submission should be marked as a spoiler (default: False). - :param spoiler: Whether or not the submission should be marked as - a spoiler (default: False). - :param timeout: Specifies a particular timeout, in seconds. Use to - avoid "Websocket error" exceptions (default: 10). - :param without_websockets: Set to ``True`` to disable use of WebSockets - (see note below for an explanation). If ``True``, this method - doesn't return anything. (default: ``False``). - :param discussion_type: Set to ``CHAT`` to enable live discussion - instead of traditional comments (default: None). - :returns: A :class:`.Submission` object for the newly created - submission, unless ``without_websockets`` is ``True``. - - :raises: :class:`.ClientException` if ``video_path`` refers to a file that is not a video. + :param timeout: Specifies a particular timeout, in seconds. Use to avoid + "Websocket error" exceptions (default: 10). + :param without_websockets: Set to ``True`` to disable use of WebSockets (see + note below for an explanation). If ``True``, this method doesn't return + anything. (default: ``False``). + :param discussion_type: Set to ``CHAT`` to enable live discussion instead of + traditional comments (default: None). + + :returns: A :class:`.Submission` object for the newly created submission, unless + ``without_websockets`` is ``True``. + + :raises: :class:`.ClientException` if ``video_path`` refers to a file that is + not a video. .. note:: - Reddit's API uses WebSockets to respond with the link of the - newly created post. If this fails, the method will raise - :class:`.WebSocketException`. Occasionally, the Reddit post will - still be created. More often, there is an error with the image - file. If you frequently get exceptions but successfully created - posts, try setting the ``timeout`` parameter to a value above 10. + Reddit's API uses WebSockets to respond with the link of the newly created + post. If this fails, the method will raise :class:`.WebSocketException`. + Occasionally, the Reddit post will still be created. More often, there is an + error with the image file. If you frequently get exceptions but successfully + created posts, try setting the ``timeout`` parameter to a value above 10. - To disable the use of WebSockets, set ``without_websockets=True``. - This will make the method return ``None``, though the post will - still be created. You may wish to do this if you are running your - program in a restricted network environment, or using a proxy - that doesn't support WebSockets connections. + To disable the use of WebSockets, set ``without_websockets=True``. This will + make the method return ``None``, though the post will still be created. You + may wish to do this if you are running your program in a restricted network + environment, or using a proxy that doesn't support WebSockets connections. For example, to submit a video to ``r/reddit_api_test`` do: @@ -1417,11 +1417,11 @@ async def submit_video( subreddit = await reddit.subreddit("reddit_api_test") await subreddit.submit_video(title, video) - .. seealso :: + .. seealso:: - * :meth:`.submit` to submit url posts and selftexts - * :meth:`.submit_image` to submit images - * :meth:`.submit_gallery`. to submit more than one image in the same post + - :meth:`.submit` to submit url posts and selftexts + - :meth:`.submit_image` to submit images + - :meth:`.submit_gallery`. to submit more than one image in the same post """ data = { @@ -1465,8 +1465,8 @@ async def subscribe( ): """Subscribe to the subreddit. - :param other_subreddits: When provided, also subscribe to the provided - list of subreddits. + :param other_subreddits: When provided, also subscribe to the provided list of + subreddits. For example, to subscribe to ``r/test``: @@ -1486,20 +1486,21 @@ async def subscribe( async def traffic(self) -> Dict[str, List[List[int]]]: """Return a dictionary of the subreddit's traffic statistics. - :raises: ``asyncprawcore.NotFound`` when the traffic stats aren't - available to the authenticated user, that is, they are not public and - the authenticated user is not a moderator of the subreddit. + :raises: ``asyncprawcore.NotFound`` when the traffic stats aren't available to + the authenticated user, that is, they are not public and the authenticated + user is not a moderator of the subreddit. - The traffic method returns a dict with three keys. The keys are - ``day``, ``hour`` and ``month``. Each key contains a list of lists with - 3 or 4 values. The first value is a timestamp indicating the start of - the category (start of the day for the ``day`` key, start of the hour - for the ``hour`` key, etc.). The second, third, and fourth values - indicate the unique pageviews, total pageviews, and subscribers, - respectively. + The traffic method returns a dict with three keys. The keys are ``day``, + ``hour`` and ``month``. Each key contains a list of lists with 3 or 4 values. + The first value is a timestamp indicating the start of the category (start of + the day for the ``day`` key, start of the hour for the ``hour`` key, etc.). The + second, third, and fourth values indicate the unique pageviews, total pageviews, + and subscribers, respectively. - .. note:: The ``hour`` key does not contain subscribers, and therefore - each sub-list contains three values. + .. note:: + + The ``hour`` key does not contain subscribers, and therefore each sub-list + contains three values. For example, to get the traffic stats for ``r/test``: @@ -1516,8 +1517,8 @@ async def unsubscribe( ): """Unsubscribe from the subreddit. - :param other_subreddits: When provided, also unsubscribe from - the provided list of subreddits. + :param other_subreddits: When provided, also unsubscribe from the provided list + of subreddits. To unsubscribe from ``r/test``: @@ -1540,8 +1541,8 @@ async def unsubscribe( class SubredditFilters: """Provide functions to interact with the special Subreddit's filters. - Members of this class should be utilized via ``Subreddit.filters``. For - example, to add a filter, run: + Members of this class should be utilized via ``Subreddit.filters``. For example, to + add a filter, run: .. code-block:: python @@ -1555,8 +1556,8 @@ def __init__(self, subreddit: "asyncpraw.models.Subreddit"): :param subreddit: The special subreddit whose filters to work with. - As of this writing filters can only be used with the special subreddits - ``all`` and ``mod``. + As of this writing filters can only be used with the special subreddits ``all`` + and ``mod``. """ self.subreddit = subreddit @@ -1572,7 +1573,7 @@ async def __aiter__( subreddit = await reddit.subreddit("NAME") async for subreddit in subreddit.filters: - ... + ... """ user = await self.subreddit._reddit.user.me() @@ -1589,18 +1590,17 @@ async def add(self, subreddit: Union["asyncpraw.models.Subreddit", str]): :param subreddit: The subreddit to add to the filter list. - Items from subreddits added to the filtered list will no longer be - included when obtaining listings for ``r/all``. + Items from subreddits added to the filtered list will no longer be included when + obtaining listings for ``r/all``. - Alternatively, you can filter a subreddit temporarily from a special - listing in a manner like so: + Alternatively, you can filter a subreddit temporarily from a special listing in + a manner like so: .. code-block:: python await reddit.subreddit("all-redditdev-learnpython") - :raises: ``asyncprawcore.NotFound`` when calling on a non-special - subreddit. + :raises: ``asyncprawcore.NotFound`` when calling on a non-special subreddit. """ user = await self.subreddit._reddit.user.me() @@ -1618,8 +1618,7 @@ async def remove(self, subreddit: Union["asyncpraw.models.Subreddit", str]): :param subreddit: The subreddit to remove from the filter list. - :raises: ``asyncprawcore.NotFound`` when calling on a non-special - subreddit. + :raises: ``asyncprawcore.NotFound`` when calling on a non-special subreddit. """ user = await self.subreddit._reddit.user.me() @@ -1640,9 +1639,9 @@ def link_templates( ) -> "asyncpraw.models.reddit.subreddit.SubredditLinkFlairTemplates": """Provide an instance of :class:`.SubredditLinkFlairTemplates`. - Use this attribute for interacting with a subreddit's link flair - templates. For example, to list all the link flair templates for a - subreddit which you have the ``flair`` moderator permission on try: + Use this attribute for interacting with a subreddit's link flair templates. For + example, to list all the link flair templates for a subreddit which you have the + ``flair`` moderator permission on try: .. code-block:: python @@ -1659,9 +1658,9 @@ def templates( ) -> "asyncpraw.models.reddit.subreddit.SubredditRedditorFlairTemplates": """Provide an instance of :class:`.SubredditRedditorFlairTemplates`. - Use this attribute for interacting with a subreddit's flair - templates. For example, to list all the flair templates for a subreddit - which you have the ``flair`` moderator permission on try: + Use this attribute for interacting with a subreddit's flair templates. For + example, to list all the flair templates for a subreddit which you have the + ``flair`` moderator permission on try: .. code-block:: python @@ -1679,8 +1678,8 @@ def __call__( ) -> Iterator["asyncpraw.models.Redditor"]: """Return a :class:`.ListingGenerator` for Redditors and their flairs. - :param redditor: When provided, yield at most a single - :class:`~.Redditor` instance (default: None). + :param redditor: When provided, yield at most a single :class:`~.Redditor` + instance (default: None). Additional keyword arguments are passed in the initialization of :class:`.ListingGenerator`. @@ -1717,17 +1716,15 @@ async def configure( ): """Update the subreddit's flair configuration. - :param position: One of left, right, or False to disable (default: - right). - :param self_assign: (boolean) Permit self assignment of user flair - (default: False). - :param link_position: One of left, right, or False to disable - (default: left). + :param position: One of left, right, or False to disable (default: right). + :param self_assign: (boolean) Permit self assignment of user flair (default: + False). + :param link_position: One of left, right, or False to disable (default: left). :param link_self_assign: (boolean) Permit self assignment of link flair (default: False). - Additional keyword arguments can be provided to handle new settings as - Reddit introduces them. + Additional keyword arguments can be provided to handle new settings as Reddit + introduces them. """ data = { @@ -1744,13 +1741,13 @@ async def configure( async def delete(self, redditor: Union["asyncpraw.models.Redditor", str]): """Delete flair for a Redditor. - :param redditor: A redditor name (e.g., ``"spez"``) or - :class:`~.Redditor` instance. + :param redditor: A redditor name (e.g., ``"spez"``) or :class:`~.Redditor` + instance. .. seealso:: - :meth:`~asyncpraw.models.reddit.subreddit.SubredditFlair.update` to - delete the flair of many Redditors at once. + :meth:`~asyncpraw.models.reddit.subreddit.SubredditFlair.update` to delete + the flair of many Redditors at once. """ url = API_PATH["deleteflair"].format(subreddit=self.subreddit) @@ -1759,8 +1756,7 @@ async def delete(self, redditor: Union["asyncpraw.models.Redditor", str]): async def delete_all(self) -> List[Dict[str, Union[str, bool, Dict[str, str]]]]: """Delete all Redditor flair in the Subreddit. - :returns: List of dictionaries indicating the success or failure of - each delete. + :returns: List of dictionaries indicating the success or failure of each delete. """ all_flairs = [x["user"] async for x in self()] @@ -1777,15 +1773,15 @@ async def set( :param redditor: (Required) A redditor name (e.g., ``"spez"``) or :class:`~.Redditor` instance. - :param text: The flair text to associate with the Redditor or - Submission (default: ""). - :param css_class: The css class to associate with the flair html - (default: ""). Use either this or ``flair_template_id``. - :param flair_template_id: The ID of the flair template to be used - (default: ``None``). Use either this or ``css_class``. + :param text: The flair text to associate with the Redditor or Submission + (default: ""). + :param css_class: The css class to associate with the flair html (default: ""). + Use either this or ``flair_template_id``. + :param flair_template_id: The ID of the flair template to be used (default: + ``None``). Use either this or ``css_class``. - This method can only be used by an authenticated user who is a - moderator of the associated Subreddit. + This method can only be used by an authenticated user who is a moderator of the + associated Subreddit. For example: @@ -1826,24 +1822,22 @@ async def update( ) -> List[Dict[str, Union[str, bool, Dict[str, str]]]]: """Set or clear the flair for many Redditors at once. - :param flair_list: Each item in this list should be either: the name of - a Redditor, an instance of :class:`.Redditor`, or a dictionary - mapping keys ``user``, ``flair_text``, and ``flair_css_class`` to - their respective values. The ``user`` key should map to a Redditor, - as described above. When a dictionary isn't provided, or the - dictionary is missing one of ``flair_text``, or ``flair_css_class`` - attributes the default values will come from the the following - arguments. - + :param flair_list: Each item in this list should be either: the name of a + Redditor, an instance of :class:`.Redditor`, or a dictionary mapping keys + ``user``, ``flair_text``, and ``flair_css_class`` to their respective + values. The ``user`` key should map to a Redditor, as described above. When + a dictionary isn't provided, or the dictionary is missing one of + ``flair_text``, or ``flair_css_class`` attributes the default values will + come from the the following arguments. :param text: The flair text to use when not explicitly provided in ``flair_list`` (default: ""). :param css_class: The css class to use when not explicitly provided in ``flair_list`` (default: ""). - :returns: List of dictionaries indicating the success or failure of - each update. - For example, to clear the flair text, and set the ``praw`` flair css - class on a few users try: + :returns: List of dictionaries indicating the success or failure of each update. + + For example, to clear the flair text, and set the ``praw`` flair css class on a + few users try: .. code-block:: python @@ -1887,21 +1881,22 @@ def __init__(self, subreddit: "asyncpraw.models.Subreddit"): :param subreddit: The subreddit whose flair templates to work with. - .. note:: This class should not be initialized directly. Instead obtain - an instance via: + .. note:: + + This class should not be initialized directly. Instead obtain an instance + via: .. code-block:: python - subreddit = await reddit.subreddit("subreddit_name") - subreddit.flair.templates + subreddit = await reddit.subreddit("subreddit_name") + subreddit.flair.templates or via .. code-block:: python - subreddit = await reddit.subreddit("subreddit_name") - subreddit.flair.link_templates - + subreddit = await reddit.subreddit("subreddit_name") + subreddit.flair.link_templates """ self.subreddit = subreddit @@ -1972,30 +1967,30 @@ async def update( ): """Update the flair template provided by ``template_id``. - :param template_id: The flair template to update. If not valid then - an exception will be thrown. + :param template_id: The flair template to update. If not valid then an exception + will be thrown. :param text: The flair template's new text (required). :param css_class: The flair template's new css_class (default: ""). - :param text_editable: (boolean) Indicate if the flair text can be - modified for each Redditor that sets it (default: False). - :param background_color: The flair template's new background color, - as a hex color. - :param text_color: The flair template's new text color, either - ``"light"`` or ``"dark"``. - :param mod_only: (boolean) Indicate if the flair can only be used by - moderators. - :param allowable_content: If specified, most be one of ``"all"``, - ``"emoji"``, or ``"text"`` to restrict content to that type. - If set to ``"emoji"`` then the ``"text"`` param must be a - valid emoji string, for example, ``":snoo:"``. - :param max_emojis: (int) Maximum emojis in the flair - (Reddit defaults this value to 10). - :param fetch: Whether or not Async PRAW will fetch existing information on - the existing flair before updating (Default: True). - - .. warning:: If parameter ``fetch`` is set to ``False``, all parameters - not provided will be reset to default (``None`` or ``False``) - values. + :param text_editable: (boolean) Indicate if the flair text can be modified for + each Redditor that sets it (default: False). + :param background_color: The flair template's new background color, as a hex + color. + :param text_color: The flair template's new text color, either ``"light"`` or + ``"dark"``. + :param mod_only: (boolean) Indicate if the flair can only be used by moderators. + :param allowable_content: If specified, most be one of ``"all"``, ``"emoji"``, + or ``"text"`` to restrict content to that type. If set to ``"emoji"`` then + the ``"text"`` param must be a valid emoji string, for example, + ``":snoo:"``. + :param max_emojis: (int) Maximum emojis in the flair (Reddit defaults this value + to 10). + :param fetch: Whether or not Async PRAW will fetch existing information on the + existing flair before updating (Default: True). + + .. warning:: + + If parameter ``fetch`` is set to ``False``, all parameters not provided will + be reset to default (``None`` or ``False``) values. For example, to make a user flair template text_editable, try: @@ -2003,9 +1998,7 @@ async def update( async for template_info in subreddit.flair.templates: await subreddit.flair.templates.update( - template_info["id"], - template_info["flair_text"], - text_editable=True + template_info["id"], template_info["flair_text"], text_editable=True ) break @@ -2074,20 +2067,19 @@ async def add( :param text: The flair template's text (required). :param css_class: The flair template's css_class (default: ""). - :param text_editable: (boolean) Indicate if the flair text can be - modified for each Redditor that sets it (default: False). - :param background_color: The flair template's new background color, - as a hex color. - :param text_color: The flair template's new text color, either - ``"light"`` or ``"dark"``. - :param mod_only: (boolean) Indicate if the flair can only be used by - moderators. - :param allowable_content: If specified, most be one of ``"all"``, - ``"emoji"``, or ``"text"`` to restrict content to that type. - If set to ``"emoji"`` then the ``"text"`` param must be a - valid emoji string, for example, ``":snoo:"``. - :param max_emojis: (int) Maximum emojis in the flair - (Reddit defaults this value to 10). + :param text_editable: (boolean) Indicate if the flair text can be modified for + each Redditor that sets it (default: False). + :param background_color: The flair template's new background color, as a hex + color. + :param text_color: The flair template's new text color, either ``"light"`` or + ``"dark"``. + :param mod_only: (boolean) Indicate if the flair can only be used by moderators. + :param allowable_content: If specified, most be one of ``"all"``, ``"emoji"``, + or ``"text"`` to restrict content to that type. If set to ``"emoji"`` then + the ``"text"`` param must be a valid emoji string, for example, + ``":snoo:"``. + :param max_emojis: (int) Maximum emojis in the flair (Reddit defaults this value + to 10). For example, to add an editable Redditor flair try: @@ -2160,28 +2152,26 @@ async def add( :param text: The flair template's text (required). :param css_class: The flair template's css_class (default: ""). - :param text_editable: (boolean) Indicate if the flair text can be - modified for each Redditor that sets it (default: False). - :param background_color: The flair template's new background color, - as a hex color. - :param text_color: The flair template's new text color, either - ``"light"`` or ``"dark"``. - :param mod_only: (boolean) Indicate if the flair can only be used by - moderators. - :param allowable_content: If specified, most be one of ``"all"``, - ``"emoji"``, or ``"text"`` to restrict content to that type. - If set to ``"emoji"`` then the ``"text"`` param must be a - valid emoji string, for example, ``":snoo:"``. - :param max_emojis: (int) Maximum emojis in the flair - (Reddit defaults this value to 10). + :param text_editable: (boolean) Indicate if the flair text can be modified for + each Redditor that sets it (default: False). + :param background_color: The flair template's new background color, as a hex + color. + :param text_color: The flair template's new text color, either ``"light"`` or + ``"dark"``. + :param mod_only: (boolean) Indicate if the flair can only be used by moderators. + :param allowable_content: If specified, most be one of ``"all"``, ``"emoji"``, + or ``"text"`` to restrict content to that type. If set to ``"emoji"`` then + the ``"text"`` param must be a valid emoji string, for example, + ``":snoo:"``. + :param max_emojis: (int) Maximum emojis in the flair (Reddit defaults this value + to 10). For example, to add an editable link flair try: .. code-block:: python subreddit = await reddit.subreddit("NAME") - await subreddit.flair.link_templates.add(css_class="praw", - text_editable=True) + await subreddit.flair.link_templates.add(css_class="praw", text_editable=True) """ await self._add( @@ -2217,8 +2207,8 @@ class SubredditModeration: .. code-block:: python - subreddit = await reddit.subreddit("test") - await subreddit.mod.accept_invite() + subreddit = await reddit.subreddit("test") + await subreddit.mod.accept_invite() """ @@ -2248,8 +2238,8 @@ def edited( ) -> Iterator[Union["asyncpraw.models.Comment", "asyncpraw.models.Submission"]]: """Return a :class:`.ListingGenerator` for edited comments and submissions. - :param only: If specified, one of ``"comments"``, or ``"submissions"`` - to yield only results of that type. + :param only: If specified, one of ``"comments"``, or ``"submissions"`` to yield + only results of that type. Additional keyword arguments are passed in the initialization of :class:`.ListingGenerator`. @@ -2278,7 +2268,9 @@ def inbox( Additional keyword arguments are passed in the initialization of :class:`.ListingGenerator`. - .. seealso:: :meth:`~.unread` for unread moderator messages. + .. seealso:: + + :meth:`~.unread` for unread moderator messages. To print the last 5 moderator mail messages and their replies, try: @@ -2305,10 +2297,9 @@ def log( ) -> Iterator["asyncpraw.models.ModAction"]: """Return a :class:`.ListingGenerator` for moderator log entries. - :param action: If given, only return log entries for the specified - action. - :param mod: If given, only return log entries for actions made by the - passed in Redditor. + :param action: If given, only return log entries for the specified action. + :param mod: If given, only return log entries for actions made by the passed in + Redditor. Additional keyword arguments are passed in the initialization of :class:`.ListingGenerator`. @@ -2335,8 +2326,8 @@ def modqueue( ) -> Iterator[Union["asyncpraw.models.Submission", "asyncpraw.models.Comment"]]: """Return a :class:`.ListingGenerator` for modqueue items. - :param only: If specified, one of ``"comments"``, or ``"submissions"`` - to yield only results of that type. + :param only: If specified, one of ``"comments"``, or ``"submissions"`` to yield + only results of that type. Additional keyword arguments are passed in the initialization of :class:`.ListingGenerator`. @@ -2377,9 +2368,9 @@ def stream(self) -> "asyncpraw.models.reddit.subreddit.SubredditModerationStream def removal_reasons(self) -> SubredditRemovalReasons: """Provide an instance of :class:`.SubredditRemovalReasons`. - Use this attribute for interacting with a subreddit's removal reasons. - For example, to list all the removal reasons for a subreddit which you - have the ``posts`` moderator permission on, try: + Use this attribute for interacting with a subreddit's removal reasons. For + example, to list all the removal reasons for a subreddit which you have the + ``posts`` moderator permission on, try: .. code-block:: python @@ -2394,8 +2385,10 @@ def removal_reasons(self) -> SubredditRemovalReasons: subreddit = await reddit.subreddit("NAME") await subreddit.mod.removal_reasons.get_reason("reason_id") - .. note:: Attempting to access attributes of an nonexistent removal - reason will result in a :class:`.ClientException`. + .. note:: + + Attempting to access attributes of an nonexistent removal reason will result + in a :class:`.ClientException`. """ return SubredditRemovalReasons(self.subreddit) @@ -2405,8 +2398,8 @@ def reports( ) -> Iterator[Union["asyncpraw.models.Submission", "asyncpraw.models.Comment"]]: """Return a :class:`.ListingGenerator` for reported comments and submissions. - :param only: If specified, one of ``"comments"``, or ``"submissions"`` - to yield only results of that type. + :param only: If specified, one of ``"comments"``, or ``"submissions"`` to yield + only results of that type. Additional keyword arguments are passed in the initialization of :class:`.ListingGenerator`. @@ -2439,8 +2432,8 @@ def spam( ) -> Iterator[Union["asyncpraw.models.Submission", "asyncpraw.models.Comment"]]: """Return a :class:`.ListingGenerator` for spam comments and submissions. - :param only: If specified, one of ``"comments"``, or ``"submissions"`` - to yield only results of that type. + :param only: If specified, one of ``"comments"``, or ``"submissions"`` to yield + only results of that type. Additional keyword arguments are passed in the initialization of :class:`.ListingGenerator`. @@ -2492,7 +2485,9 @@ def unread( Additional keyword arguments are passed in the initialization of :class:`.ListingGenerator`. - .. seealso:: :meth:`inbox` for all messages. + .. seealso:: + + :meth:`inbox` for all messages. To print the mail in the unread modmail queue try: @@ -2516,79 +2511,77 @@ async def update( See https://www.reddit.com/dev/api#POST_api_site_admin for the full list. - :param all_original_content: Mandate all submissions to be original - content only. - :param allow_chat_post_creation: Allow users to create chat - submissions. - :param allow_images: Allow users to upload images using the native - image hosting. + :param all_original_content: Mandate all submissions to be original content + only. + :param allow_chat_post_creation: Allow users to create chat submissions. + :param allow_images: Allow users to upload images using the native image + hosting. :param allow_polls: Allow users to post polls to the subreddit. - :param allow_post_crossposts: Allow users to crosspost submissions from - other subreddits. - :param allow_videos: Allow users to upload videos using the native - image hosting. - :param collapse_deleted_comments: Collapse deleted and removed comments - on comments pages by default.:param comment_score_hide_mins: The number of minutes to hide comment scores. + :param allow_post_crossposts: Allow users to crosspost submissions from other + subreddits. + :param allow_videos: Allow users to upload videos using the native image + hosting. + :param collapse_deleted_comments: Collapse deleted and removed comments on + comments pages by default. + :param comment_score_hide_mins: The number of minutes to hide comment scores. :param content_options: The types of submissions users can make. One of ``any``, ``link``, ``self``. - :param crowd_control_chat_level: Controls the crowd control level for - chat rooms. Goes from 0-3. - :param crowd_control_level: Controls the crowd control level for - submissions. Goes from 0-3. + :param crowd_control_chat_level: Controls the crowd control level for chat + rooms. Goes from 0-3. + :param crowd_control_level: Controls the crowd control level for submissions. + Goes from 0-3. :param crowd_control_mode: Enables/disables crowd control. :param default_set: Allow the subreddit to appear on ``r/all`` as well as the default and trending lists. - :param disable_contributor_requests: Specifies whether redditors may - send automated modmail messages requesting approval as a submitter. - :param exclude_banned_modqueue: Exclude posts by site-wide banned users - from modqueue/unmoderated. - :param free_form_reports: Allow users to specify custom reasons in the - report menu. + :param disable_contributor_requests: Specifies whether redditors may send + automated modmail messages requesting approval as a submitter. + :param exclude_banned_modqueue: Exclude posts by site-wide banned users from + modqueue/unmoderated. + :param free_form_reports: Allow users to specify custom reasons in the report + menu. :param header_hover_text: The text seen when hovering over the snoo. :param hide_ads: Don't show ads within this subreddit. Only applies to Premium-user only subreddits. - :param key_color: A 6-digit rgb hex color (e.g. ``"#AABBCC"``), used as - a thematic color for your subreddit on mobile. + :param key_color: A 6-digit rgb hex color (e.g. ``"#AABBCC"``), used as a + thematic color for your subreddit on mobile. :param language: A valid IETF language tag (underscore separated). - :param original_content_tag_enabled: Enables the use of the - ``original content`` label for submissions. + :param original_content_tag_enabled: Enables the use of the ``original content`` + label for submissions. :param over_18: Viewers must be over 18 years old (i.e. NSFW). - :param public_description: Public description blurb. Appears in search - results and on the landing page for private subreddits. - :param restrict_commenting: Specifies whether approved users have the - ability to comment. - :param restrict_posting: Specifies whether approved users have the - ability to submit posts. + :param public_description: Public description blurb. Appears in search results + and on the landing page for private subreddits. + :param restrict_commenting: Specifies whether approved users have the ability to + comment. + :param restrict_posting: Specifies whether approved users have the ability to + submit posts. :param show_media: Show thumbnails on submissions. :param show_media_preview: Expand media previews on comments pages. - :param spam_comments: Spam filter strength for comments. - One of ``all``, ``low``, ``high``. - :param spam_links: Spam filter strength for links. - One of ``all``, ``low``, ``high``. - :param spam_selfposts: Spam filter strength for selfposts. - One of ``all``, ``low``, ``high``. + :param spam_comments: Spam filter strength for comments. One of ``all``, + ``low``, ``high``. + :param spam_links: Spam filter strength for links. One of ``all``, ``low``, + ``high``. + :param spam_selfposts: Spam filter strength for selfposts. One of ``all``, + ``low``, ``high``. :param spoilers_enabled: Enable marking posts as containing spoilers. - :param submit_link_label: Custom label for submit link button - (None for default). + :param submit_link_label: Custom label for submit link button (None for + default). :param submit_text: Text to show on submission page. - :param submit_text_label: Custom label for submit text post button - (None for default). + :param submit_text_label: Custom label for submit text post button (None for + default). :param subreddit_type: One of ``archived``, ``employees_only``, ``gold_only``, ``gold_restricted``, ``private``, ``public``, ``restricted``. - :paramsuggested_comment_sort: All comment threads will use this - sorting method by default. Leave None, or choose one of - ``confidence``, ``controversial``, ``live``, ``new``, ``old``, - ``qa``, ``random``, ``top``. + :param suggested_comment_sort: All comment threads will use this sorting method + by default. Leave None, or choose one of ``confidence``, ``controversial``, + ``live``, ``new``, ``old``, ``qa``, ``random``, ``top``. :param title: The title of the subreddit. :param welcome_message_enabled: Enables the subreddit welcome message. - :param welcome_message_text: The text to be used as a welcome message. - A welcome message is sent to all new subscribers by a Reddit bot. - :param wiki_edit_age: Account age, in days, required to edit and create - wiki pages. + :param welcome_message_text: The text to be used as a welcome message. A welcome + message is sent to all new subscribers by a Reddit bot. + :param wiki_edit_age: Account age, in days, required to edit and create wiki + pages. :param wiki_edit_karma: "asyncpraw.models.Subreddit" karma required to edit and - create - wiki pages. - :param wikimode: One of ``anyone``, ``disabled``, ``modonly``. + create wiki pages. + :param wikimode: One of ``anyone``, ``disabled``, ``modonly``. .. note:: @@ -2602,12 +2595,12 @@ async def update( sidebar = await subreddit.wiki.get_page("config/sidebar") await sidebar.edit(content="new sidebar content") - Additional keyword arguments can be provided to handle new settings as - Reddit introduces them. + Additional keyword arguments can be provided to handle new settings as Reddit + introduces them. - Settings that are documented here and aren't explicitly set by you in a - call to :meth:`.SubredditModeration.update` should retain their current - value. If they do not, please file a bug. + Settings that are documented here and aren't explicitly set by you in a call to + :meth:`.SubredditModeration.update` should retain their current value. If they + do not, please file a bug. """ if not self.subreddit._fetched: @@ -2645,13 +2638,13 @@ def edited( ]: """Yield edited comments and submissions as they become available. - :param only: If specified, one of ``"comments"``, or ``"submissions"`` - to yield only results of that type. + :param only: If specified, one of ``"comments"``, or ``"submissions"`` to yield + only results of that type. Keyword arguments are passed to :func:`.stream_generator`. - For example, to retrieve all new edited submissions/comments made - to all moderated subreddits, try: + For example, to retrieve all new edited submissions/comments made to all + moderated subreddits, try: .. code-block:: python @@ -2670,13 +2663,12 @@ def log( ) -> AsyncGenerator["asyncpraw.models.ModAction", None]: """Yield moderator log entries as they become available. - :param action: If given, only return log entries for the specified - action. - :param mod: If given, only return log entries for actions made by the - passed in Redditor. + :param action: If given, only return log entries for the specified action. + :param mod: If given, only return log entries for actions made by the passed in + Redditor. - For example, to retrieve all new mod actions made to all moderated - subreddits, try: + For example, to retrieve all new mod actions made to all moderated subreddits, + try: .. code-block:: python @@ -2702,10 +2694,9 @@ def modmail_conversations( ) -> AsyncGenerator[ModmailConversation, None]: """Yield new-modmail conversations as they become available. - :param other_subreddits: A list of :class:`.Subreddit` instances for - which to fetch conversations (default: None). - :param sort: Can be one of: mod, recent, unread, user - (default: recent). + :param other_subreddits: A list of :class:`.Subreddit` instances for which to + fetch conversations (default: None). + :param sort: Can be one of: mod, recent, unread, user (default: recent). :param state: Can be one of: all, appeals, archived, default, highlighted, inbox, inprogress, mod, new, notifications (default: all). "all" does not include mod or archived conversations. "inbox" does not include appeals @@ -2741,8 +2732,8 @@ def modqueue( ]: """Yield comments/submissions in the modqueue as they become available. - :param only: If specified, one of ``"comments"``, or ``"submissions"`` - to yield only results of that type. + :param only: If specified, one of ``"comments"``, or ``"submissions"`` to yield + only results of that type. Keyword arguments are passed to :func:`.stream_generator`. @@ -2766,8 +2757,8 @@ def reports( ]: """Yield reported comments and submissions as they become available. - :param only: If specified, one of ``"comments"``, or ``"submissions"`` - to yield only results of that type. + :param only: If specified, one of ``"comments"``, or ``"submissions"`` to yield + only results of that type. Keyword arguments are passed to :func:`.stream_generator`. @@ -2789,8 +2780,8 @@ def spam( ]: """Yield spam comments and submissions as they become available. - :param only: If specified, one of ``"comments"``, or ``"submissions"`` - to yield only results of that type. + :param only: If specified, one of ``"comments"``, or ``"submissions"`` to yield + only results of that type. Keyword arguments are passed to :func:`.stream_generator`. @@ -2830,7 +2821,9 @@ def unread( Keyword arguments are passed to :func:`.stream_generator`. - .. seealso:: :meth:`~.inbox` for all messages. + .. seealso:: + + :meth:`~.inbox` for all messages. To print new mail in the unread modmail queue try: @@ -2912,8 +2905,8 @@ async def opt_out(self): class SubredditRelationship: """Represents a relationship between a redditor and subreddit. - Instances of this class can be iterated through in order to discover the - Redditors that make up the relationship. + Instances of this class can be iterated through in order to discover the Redditors + that make up the relationship. For example, banned users of a subreddit can be iterated through like so: @@ -2932,10 +2925,9 @@ def __call__( ) -> Iterator["asyncpraw.models.Redditor"]: """Return a :class:`.ListingGenerator` for Redditors in the relationship. - :param redditor: When provided, yield at most a single - :class:`~.Redditor` instance. This is useful to confirm if a - relationship exists, or to fetch the metadata associated with a - particular relationship (default: None). + :param redditor: When provided, yield at most a single :class:`~.Redditor` + instance. This is useful to confirm if a relationship exists, or to fetch + the metadata associated with a particular relationship (default: None). Additional keyword arguments are passed in the initialization of :class:`.ListingGenerator`. @@ -2960,8 +2952,8 @@ async def add( ): """Add ``redditor`` to this relationship. - :param redditor: A redditor name (e.g., ``"spez"``) or - :class:`~.Redditor` instance. + :param redditor: A redditor name (e.g., ``"spez"``) or :class:`~.Redditor` + instance. """ data = {"name": str(redditor), "type": self.relationship} @@ -2972,8 +2964,8 @@ async def add( async def remove(self, redditor: Union[str, "asyncpraw.models.Redditor"]): """Remove ``redditor`` from this relationship. - :param redditor: A redditor name (e.g., ``"spez"``) or - :class:`~.Redditor` instance. + :param redditor: A redditor name (e.g., ``"spez"``) or :class:`~.Redditor` + instance. """ data = {"name": str(redditor), "type": self.relationship} @@ -3051,13 +3043,15 @@ async def __call__( """Return a list of Redditors who are moderators. :param redditor: When provided, return a list containing at most one - :class:`~.Redditor` instance. This is useful to confirm if a - relationship exists, or to fetch the metadata associated with a - particular relationship (default: None). + :class:`~.Redditor` instance. This is useful to confirm if a relationship + exists, or to fetch the metadata associated with a particular relationship + (default: None). + + .. note:: - .. note:: Unlike other relationship callables, this relationship is not - paginated. Thus it simply returns the full list, rather than - an iterator for the results. + Unlike other relationship callables, this relationship is not paginated. + Thus it simply returns the full list, rather than an iterator for the + results. To be used like: @@ -3080,18 +3074,17 @@ async def add( ): """Add or invite ``redditor`` to be a moderator of the subreddit. - :param redditor: A redditor name (e.g., ``"spez"``) or - :class:`~.Redditor` instance. - :param permissions: When provided (not ``None``), permissions should be - a list of strings specifying which subset of permissions to - grant. An empty list ``[]`` indicates no permissions, and when not - provided ``None``, indicates full permissions. + :param redditor: A redditor name (e.g., ``"spez"``) or :class:`~.Redditor` + instance. + :param permissions: When provided (not ``None``), permissions should be a list + of strings specifying which subset of permissions to grant. An empty list + ``[]`` indicates no permissions, and when not provided ``None``, indicates + full permissions. - An invite will be sent unless the user making this call is an admin - user. + An invite will be sent unless the user making this call is an admin user. - For example, to invite ``"spez"`` with ``"posts"`` and ``"mail"`` - permissions to ``r/test``, try: + For example, to invite ``"spez"`` with ``"posts"`` and ``"mail"`` permissions to + ``r/test``, try: .. code-block:: python @@ -3112,12 +3105,12 @@ async def invite( ): """Invite ``redditor`` to be a moderator of the subreddit. - :param redditor: A redditor name (e.g., ``"spez"``) or - :class:`~.Redditor` instance. - :param permissions: When provided (not ``None``), permissions should be - a list of strings specifying which subset of permissions to - grant. An empty list ``[]`` indicates no permissions, and when not - provided ``None``, indicates full permissions. + :param redditor: A redditor name (e.g., ``"spez"``) or :class:`~.Redditor` + instance. + :param permissions: When provided (not ``None``), permissions should be a list + of strings specifying which subset of permissions to grant. An empty list + ``[]`` indicates no permissions, and when not provided ``None``, indicates + full permissions. For example, to invite ``"spez"`` with ``posts`` and ``mail`` permissions to ``r/test``, try: @@ -3185,8 +3178,8 @@ async def leave(self): async def remove_invite(self, redditor: Union[str, "asyncpraw.models.Redditor"]): """Remove the moderator invite for ``redditor``. - :param redditor: A redditor name (e.g., ``"spez"``) or - :class:`~.Redditor` instance. + :param redditor: A redditor name (e.g., ``"spez"``) or :class:`~.Redditor` + instance. For example: @@ -3207,12 +3200,12 @@ async def update( ): """Update the moderator permissions for ``redditor``. - :param redditor: A redditor name (e.g., ``"spez"``) or - :class:`~.Redditor` instance. - :param permissions: When provided (not ``None``), permissions should be - a list of strings specifying which subset of permissions to - grant. An empty list ``[]`` indicates no permissions, and when not - provided, ``None``, indicates full permissions. + :param redditor: A redditor name (e.g., ``"spez"``) or :class:`~.Redditor` + instance. + :param permissions: When provided (not ``None``), permissions should be a list + of strings specifying which subset of permissions to grant. An empty list + ``[]`` indicates no permissions, and when not provided, ``None``, indicates + full permissions. For example, to add all permissions to the moderator, try: @@ -3240,15 +3233,15 @@ async def update_invite( ): """Update the moderator invite permissions for ``redditor``. - :param redditor: A redditor name (e.g., ``"spez"``) or - :class:`~.Redditor` instance. - :param permissions: When provided (not ``None``), permissions should be - a list of strings specifying which subset of permissions to - grant. An empty list ``[]`` indicates no permissions, and when not - provided, ``None``, indicates full permissions. + :param redditor: A redditor name (e.g., ``"spez"``) or :class:`~.Redditor` + instance. + :param permissions: When provided (not ``None``), permissions should be a list + of strings specifying which subset of permissions to grant. An empty list + ``[]`` indicates no permissions, and when not provided, ``None``, indicates + full permissions. - For example, to grant the ``flair``` and ``mail``` permissions to - the moderator invite, try: + For example, to grant the ``flair``` and ``mail``` permissions to the moderator + invite, try: .. code-block:: python @@ -3265,9 +3258,8 @@ async def update_invite( class Modmail: """Provides modmail functions for a subreddit. - For example, to send a new modmail from the subreddit ``r/test`` to user - ``u/spez`` with the subject ``test`` along with a message body of - ``hello``: + For example, to send a new modmail from the subreddit ``r/test`` to user ``u/spez`` + with the subject ``test`` along with a message body of ``hello``: .. code-block:: python @@ -3292,8 +3284,8 @@ async def __call__( subreddit = await reddit.subreddit("redditdev") await subreddit.modmail("2gmz", mark_read=True) - If you don't need the object fetched right away (e.g., to utilize a - class method) you can do: + If you don't need the object fetched right away (e.g., to utilize a class + method) you can do: .. code-block:: python @@ -3310,11 +3302,10 @@ class method) you can do: for message in conversation.messages: print(message.body_markdown) - ``ModmailConversation.user`` is a special instance of - :class:`.Redditor` with extra attributes describing the non-moderator - user's recent posts, comments, and modmail messages within the - subreddit, as well as information on active bans and mutes. This - attribute does not exist on internal moderator discussions. + ``ModmailConversation.user`` is a special instance of :class:`.Redditor` with + extra attributes describing the non-moderator user's recent posts, comments, and + modmail messages within the subreddit, as well as information on active bans and + mutes. This attribute does not exist on internal moderator discussions. For example, to print the user's ban status: @@ -3361,15 +3352,16 @@ async def bulk_read( ) -> List[ModmailConversation]: """Mark conversations for subreddit(s) as read. - Due to server-side restrictions, "all" is not a valid subreddit for - this method. Instead, use :meth:`~.Modmail.subreddits` to get a list of - subreddits using the new modmail. + Due to server-side restrictions, "all" is not a valid subreddit for this method. + Instead, use :meth:`~.Modmail.subreddits` to get a list of subreddits using the + new modmail. + + :param other_subreddits: A list of :class:`.Subreddit` instances for which to + mark conversations (default: None). + :param state: Can be one of: all, archived, highlighted, inprogress, mod, new, + notifications, or appeals, (default: all). "all" does not include internal, + archived, or appeals conversations. - :param other_subreddits: A list of :class:`.Subreddit` instances for - which to mark conversations (default: None). - :param state: Can be one of: all, archived, highlighted, inprogress, - mod, new, notifications, or appeals, (default: all). "all" does not - include internal, archived, or appeals conversations. :returns: A list of lazy :class:`.ModmailConversation` instances that were marked read. @@ -3402,18 +3394,16 @@ async def conversations( ) -> AsyncGenerator[ModmailConversation, None]: # noqa: D207, D301 """Generate :class:`.ModmailConversation` objects for subreddit(s). - :param after: A base36 modmail conversation id. When provided, the - listing begins after this conversation (default: None). - :param limit: The maximum number of conversations to fetch. If None, - the server-side default is 25 at the time of writing - (default: None). - :param other_subreddits: A list of :class:`.Subreddit` instances for - which to fetch conversations (default: None). - :param sort: Can be one of: mod, recent, unread, user - (default: recent). - :param state: Can be one of: all, archived, highlighted, inprogress, - mod, new, notifications, or appeals, (default: all). "all" does not - include internal, archived, or appeals conversations. + :param after: A base36 modmail conversation id. When provided, the listing + begins after this conversation (default: None). + :param limit: The maximum number of conversations to fetch. If None, the + server-side default is 25 at the time of writing (default: None). + :param other_subreddits: A list of :class:`.Subreddit` instances for which to + fetch conversations (default: None). + :param sort: Can be one of: mod, recent, unread, user (default: recent). + :param state: Can be one of: all, archived, highlighted, inprogress, mod, new, + notifications, or appeals, (default: all). "all" does not include internal, + archived, or appeals conversations. For example: @@ -3463,8 +3453,9 @@ async def create( :param body: The message body. Cannot be empty. :param recipient: The recipient; a username or an instance of :class:`.Redditor`. - :param author_hidden: When True, author is hidden from non-moderators - (default: False). + :param author_hidden: When True, author is hidden from non-moderators (default: + False). + :returns: A :class:`.ModmailConversation` object for the newly created conversation. @@ -3512,8 +3503,8 @@ async def subreddits( async def unread_count(self) -> Dict[str, int]: """Return unread conversation count by conversation state. - At time of writing, possible states are: archived, highlighted, - inprogress, mod, new, notifications, or appeals. + At time of writing, possible states are: archived, highlighted, inprogress, mod, + new, notifications, or appeals. :returns: A dict mapping conversation states to unread counts. @@ -3545,16 +3536,17 @@ def comments( ) -> AsyncGenerator["asyncpraw.models.Comment", None]: """Yield new comments as they become available. - Comments are yielded oldest first. Up to 100 historical comments will - initially be returned. + Comments are yielded oldest first. Up to 100 historical comments will initially + be returned. Keyword arguments are passed to :func:`.stream_generator`. - .. note:: While Async PRAW tries to catch all new comments, some high-volume - streams, especially the r/all stream, may drop some comments. + .. note:: + + While Async PRAW tries to catch all new comments, some high-volume streams, + especially the r/all stream, may drop some comments. - For example, to retrieve all new comments made to the ``iama`` - subreddit, try: + For example, to retrieve all new comments made to the ``iama`` subreddit, try: .. code-block:: python @@ -3562,8 +3554,8 @@ def comments( async for comment in subreddit.stream.comments(): print(comment) - To only retrieve new submissions starting when the stream is - created, pass ``skip_existing=True``: + To only retrieve new submissions starting when the stream is created, pass + ``skip_existing=True``: .. code-block:: python @@ -3579,14 +3571,15 @@ def submissions( ) -> AsyncGenerator["asyncpraw.models.Submission", None]: """Yield new submissions as they become available. - Submissions are yielded oldest first. Up to 100 historical submissions - will initially be returned. + Submissions are yielded oldest first. Up to 100 historical submissions will + initially be returned. Keyword arguments are passed to :func:`.stream_generator`. - .. note:: While Async PRAW tries to catch all new submissions, some - high-volume streams, especially the r/all stream, may drop some - submissions. + .. note:: + + While Async PRAW tries to catch all new submissions, some high-volume + streams, especially the r/all stream, may drop some submissions. For example, to retrieve all new submissions made to all of Reddit, try: @@ -3603,8 +3596,7 @@ def submissions( class SubredditStylesheet: """Provides a set of stylesheet functions to a Subreddit. - For example, to add the css data ``.test{color:blue}`` to the existing - stylesheet: + For example, to add the css data ``.test{color:blue}`` to the existing stylesheet: .. code-block:: python @@ -3709,8 +3701,8 @@ async def delete_banner(self): async def delete_banner_additional_image(self): """Remove the current subreddit (redesign) banner additional image. - Succeeds even if there is no additional image. Will also delete any - configured hover image. + Succeeds even if there is no additional image. Will also delete any configured + hover image. For example: @@ -3828,19 +3820,19 @@ async def update(self, stylesheet: str, reason: Optional[str] = None): async def upload(self, name: str, image_path: str) -> Dict[str, str]: """Upload an image to the Subreddit. - :param name: The name to use for the image. If an image already exists - with the same name, it will be replaced. + :param name: The name to use for the image. If an image already exists with the + same name, it will be replaced. :param image_path: A path to a jpeg or png image. - :returns: A dictionary containing a link to the uploaded image under - the key ``img_src``. - :raises: ``asyncprawcore.TooLarge`` if the overall request body is too - large. + :returns: A dictionary containing a link to the uploaded image under the key + ``img_src``. + + :raises: ``asyncprawcore.TooLarge`` if the overall request body is too large. :raises: :class:`.RedditAPIException` if there are other issues with the - uploaded image. Unfortunately the exception info might not be very - specific, so try through the website with the same image to see what - the problem actually might be. + uploaded image. Unfortunately the exception info might not be very specific, + so try through the website with the same image to see what the problem + actually might be. For example: @@ -3862,9 +3854,9 @@ async def upload_banner(self, image_path: str): :raises: ``asyncprawcore.TooLarge`` if the overall request body is too large. :raises: :class:`.RedditAPIException` if there are other issues with the - uploaded image. Unfortunately the exception info might not be very - specific, so try through the website with the same image to see what - the problem actually might be. + uploaded image. Unfortunately the exception info might not be very specific, + so try through the website with the same image to see what the problem + actually might be. For example: @@ -3884,15 +3876,14 @@ async def upload_banner_additional_image( """Upload an image for the subreddit's (redesign) additional image. :param image_path: A path to a jpeg or png image. - :param align: Either ``left``, ``centered``, or ``right``. (default: - ``left``). + :param align: Either ``left``, ``centered``, or ``right``. (default: ``left``). :raises: ``asyncprawcore.TooLarge`` if the overall request body is too large. :raises: :class:`.RedditAPIException` if there are other issues with the - uploaded image. Unfortunately the exception info might not be very - specific, so try through the website with the same image to see what - the problem actually might be. + uploaded image. Unfortunately the exception info might not be very specific, + so try through the website with the same image to see what the problem + actually might be. For example: @@ -3927,9 +3918,9 @@ async def upload_banner_hover_image(self, image_path: str): :raises: ``asyncprawcore.TooLarge`` if the overall request body is too large. :raises: :class:`.RedditAPIException` if there are other issues with the - uploaded image. Unfortunately the exception info might not be very - specific, so try through the website with the same image to see what - the problem actually might be. + uploaded image. Unfortunately the exception info might not be very specific, + so try through the website with the same image to see what the problem + actually might be. For example: @@ -3947,15 +3938,16 @@ async def upload_header(self, image_path: str) -> Dict[str, str]: """Upload an image to be used as the Subreddit's header image. :param image_path: A path to a jpeg or png image. - :returns: A dictionary containing a link to the uploaded image under - the key ``img_src``. + + :returns: A dictionary containing a link to the uploaded image under the key + ``img_src``. :raises: ``asyncprawcore.TooLarge`` if the overall request body is too large. :raises: :class:`.RedditAPIException` if there are other issues with the - uploaded image. Unfortunately the exception info might not be very - specific, so try through the website with the same image to see what - the problem actually might be. + uploaded image. Unfortunately the exception info might not be very specific, + so try through the website with the same image to see what the problem + actually might be. For example: @@ -3971,15 +3963,16 @@ async def upload_mobile_header(self, image_path: str) -> Dict[str, str]: """Upload an image to be used as the Subreddit's mobile header. :param image_path: A path to a jpeg or png image. - :returns: A dictionary containing a link to the uploaded image under - the key ``img_src``. + + :returns: A dictionary containing a link to the uploaded image under the key + ``img_src``. :raises: ``asyncprawcore.TooLarge`` if the overall request body is too large. :raises: :class:`.RedditAPIException` if there are other issues with the - uploaded image. Unfortunately the exception info might not be very - specific, so try through the website with the same image to see what - the problem actually might be. + uploaded image. Unfortunately the exception info might not be very specific, + so try through the website with the same image to see what the problem + actually might be. For example: @@ -3995,15 +3988,16 @@ async def upload_mobile_icon(self, image_path: str) -> Dict[str, str]: """Upload an image to be used as the Subreddit's mobile icon. :param image_path: A path to a jpeg or png image. - :returns: A dictionary containing a link to the uploaded image under - the key ``img_src``. + + :returns: A dictionary containing a link to the uploaded image under the key + ``img_src``. :raises: ``asyncprawcore.TooLarge`` if the overall request body is too large. :raises: :class:`.RedditAPIException` if there are other issues with the - uploaded image. Unfortunately the exception info might not be very - specific, so try through the website with the same image to see what - the problem actually might be. + uploaded image. Unfortunately the exception info might not be very specific, + so try through the website with the same image to see what the problem + actually might be. For example: @@ -4076,8 +4070,7 @@ async def create( ): """Create a new wiki page. - :param name: The name of the new WikiPage. This name will be - normalized. + :param name: The name of the new WikiPage. This name will be normalized. :param content: The content of the new WikiPage. :param reason: (Optional) The reason for the creation. :param other_settings: Additional keyword arguments to pass. diff --git a/asyncpraw/models/reddit/widgets.py b/asyncpraw/models/reddit/widgets.py index 417b0b7b1..f9b3c8fac 100755 --- a/asyncpraw/models/reddit/widgets.py +++ b/asyncpraw/models/reddit/widgets.py @@ -14,31 +14,30 @@ class Button(AsyncPRAWBase): **Typical Attributes** - This table describes attributes that typically belong to objects of this - class. Since attributes are dynamically provided (see - :ref:`determine-available-attributes-of-an-object`), there is not a - guarantee that these attributes will always be present, nor is this list - necessarily complete. - - ======================= =================================================== - Attribute Description - ======================= =================================================== - ``color`` The hex color used to outline the button. - ``fillColor`` The hex color for the background of the button. - ``height`` Image height. Only present on image buttons. - ``hoverState`` A ``dict`` describing the state of the button when - hovered over. Optional. - ``kind`` Either ``"text"`` or ``"image"``. - ``linkUrl`` A link that can be visited by clicking the button. - Only present on image buttons. - ``text`` The text displayed on the button. - ``textColor`` The hex color for the text of the button. - ``url`` * If the button is a text button, a link that can - be visited by clicking the button. - * If the button is an image button, the URL of a - Reddit-hosted image. - ``width`` Image width. Only present on image buttons. - ======================= =================================================== + This table describes attributes that typically belong to objects of this class. + Since attributes are dynamically provided (see + :ref:`determine-available-attributes-of-an-object`), there is not a guarantee that + these attributes will always be present, nor is this list necessarily complete. + + ============== ===================================================================== + Attribute Description + ============== ===================================================================== + ``color`` The hex color used to outline the button. + ``fillColor`` The hex color for the background of the button. + ``height`` Image height. Only present on image buttons. + ``hoverState`` A ``dict`` describing the state of the button when hovered over. + Optional. + ``kind`` Either ``"text"`` or ``"image"``. + ``linkUrl`` A link that can be visited by clicking the button. Only present on + image buttons. + ``text`` The text displayed on the button. + ``textColor`` The hex color for the text of the button. + ``url`` - If the button is a text button, a link that can be visited by + clicking the button. + - If the button is an image button, the URL of a Reddit-hosted image. + ``width`` Image width. Only present on image buttons. + ============== ===================================================================== + """ @@ -47,54 +46,53 @@ class CalendarConfiguration(AsyncPRAWBase): **Typical Attributes** - This table describes attributes that typically belong to objects of this - class. Since attributes are dynamically provided (see - :ref:`determine-available-attributes-of-an-object`), there is not a - guarantee that these attributes will always be present, nor is this list - necessarily complete. - - ======================= =================================================== - Attribute Description - ======================= =================================================== - ``numEvents`` The number of events to display on the calendar. - ``showDate`` Whether or not to show the dates of events. - ``showDescription`` Whether or not to show the descriptions of events. - ``showLocation`` Whether or not to show the locations of events. - ``showTime`` Whether or not to show the times of events. - ``showTitle`` Whether or not to show the titles of events. - ======================= =================================================== + This table describes attributes that typically belong to objects of this class. + Since attributes are dynamically provided (see + :ref:`determine-available-attributes-of-an-object`), there is not a guarantee that + these attributes will always be present, nor is this list necessarily complete. + + =================== ================================================== + Attribute Description + =================== ================================================== + ``numEvents`` The number of events to display on the calendar. + ``showDate`` Whether or not to show the dates of events. + ``showDescription`` Whether or not to show the descriptions of events. + ``showLocation`` Whether or not to show the locations of events. + ``showTime`` Whether or not to show the times of events. + ``showTitle`` Whether or not to show the titles of events. + =================== ================================================== + """ class Hover(AsyncPRAWBase): """Class to represent the hover data for a :class:`.ButtonWidget`. - These values will take effect when the button is hovered over (the user - moves their cursor so it's on top of the button). + These values will take effect when the button is hovered over (the user moves their + cursor so it's on top of the button). **Typical Attributes** - This table describes attributes that typically belong to objects of this - class. Since attributes are dynamically provided (see - :ref:`determine-available-attributes-of-an-object`), there is not a - guarantee that these attributes will always be present, nor is this list - comprehensive in any way. - - ======================= =================================================== - Attribute Description - ======================= =================================================== - ``color`` The hex color used to outline the button. - ``fillColor`` The hex color for the background of the button. - ``textColor`` The hex color for the text of the button. - ``height`` Image height. Only present on image buttons. - ``kind`` Either ``text`` or ``image``. - ``text`` The text displayed on the button. - ``url`` * If the button is a text button, a link that can - be visited by clicking the button. - * If the button is an image button, the URL of a - Reddit-hosted image. - ``width`` Image width. Only present on image buttons. - ======================= =================================================== + This table describes attributes that typically belong to objects of this class. + Since attributes are dynamically provided (see + :ref:`determine-available-attributes-of-an-object`), there is not a guarantee that + these attributes will always be present, nor is this list comprehensive in any way. + + ============= ===================================================================== + Attribute Description + ============= ===================================================================== + ``color`` The hex color used to outline the button. + ``fillColor`` The hex color for the background of the button. + ``textColor`` The hex color for the text of the button. + ``height`` Image height. Only present on image buttons. + ``kind`` Either ``text`` or ``image``. + ``text`` The text displayed on the button. + ``url`` - If the button is a text button, a link that can be visited by + clicking the button. + - If the button is an image button, the URL of a Reddit-hosted image. + ``width`` Image width. Only present on image buttons. + ============= ===================================================================== + """ @@ -103,20 +101,20 @@ class Image(AsyncPRAWBase): **Typical Attributes** - This table describes attributes that typically belong to objects of this - class. Since attributes are dynamically provided (see - :ref:`determine-available-attributes-of-an-object`), there is not a - guarantee that these attributes will always be present, nor is this list - necessarily complete. - - ======================= =================================================== - Attribute Description - ======================= =================================================== - ``height`` Image height. - ``linkUrl`` A link that can be visited by clicking the image. - ``url`` The URL of the (Reddit-hosted) image. - ``width`` Image width. - ======================= =================================================== + This table describes attributes that typically belong to objects of this class. + Since attributes are dynamically provided (see + :ref:`determine-available-attributes-of-an-object`), there is not a guarantee that + these attributes will always be present, nor is this list necessarily complete. + + =========== ================================================= + Attribute Description + =========== ================================================= + ``height`` Image height. + ``linkUrl`` A link that can be visited by clicking the image. + ``url`` The URL of the (Reddit-hosted) image. + ``width`` Image width. + =========== ================================================= + """ @@ -125,20 +123,20 @@ class ImageData(AsyncPRAWBase): **Typical Attributes** - This table describes attributes that typically belong to objects of this - class. Since attributes are dynamically provided (see - :ref:`determine-available-attributes-of-an-object`), there is not a - guarantee that these attributes will always be present, nor is this list - necessarily complete. - - ======================= =================================================== - Attribute Description - ======================= =================================================== - ``height`` The image height. - ``name`` The image name. - ``url`` The URL of the image on Reddit's servers. - ``width`` The image width. - ======================= =================================================== + This table describes attributes that typically belong to objects of this class. + Since attributes are dynamically provided (see + :ref:`determine-available-attributes-of-an-object`), there is not a guarantee that + these attributes will always be present, nor is this list necessarily complete. + + ========== ========================================= + Attribute Description + ========== ========================================= + ``height`` The image height. + ``name`` The image name. + ``url`` The URL of the image on Reddit's servers. + ``width`` The image width. + ========== ========================================= + """ @@ -147,18 +145,18 @@ class MenuLink(AsyncPRAWBase): **Typical Attributes** - This table describes attributes that typically belong to objects of this - class. Since attributes are dynamically provided (see - :ref:`determine-available-attributes-of-an-object`), there is not a - guarantee that these attributes will always be present, nor is this list - necessarily complete. - - ======================= =================================================== - Attribute Description - ======================= =================================================== - ``text`` The text of the menu link. - ``url`` The URL that the menu item links to. - ======================= =================================================== + This table describes attributes that typically belong to objects of this class. + Since attributes are dynamically provided (see + :ref:`determine-available-attributes-of-an-object`), there is not a guarantee that + these attributes will always be present, nor is this list necessarily complete. + + ========= ==================================== + Attribute Description + ========= ==================================== + ``text`` The text of the menu link. + ``url`` The URL that the menu item links to. + ========= ==================================== + """ @@ -167,20 +165,20 @@ class Styles(AsyncPRAWBase): **Typical Attributes** - This table describes attributes that typically belong to objects of this - class. Since attributes are dynamically provided (see - :ref:`determine-available-attributes-of-an-object`), there is not a - guarantee that these attributes will always be present, nor is this list - comprehensive in any way. - - ======================= =================================================== - Attribute Description - ======================= =================================================== - ``backgroundColor`` The background color of a widget, given as a - hexadecimal (``0x######``). - ``headerColor`` The header color of a widget, given as a - hexadecimal (``0x######``). - ======================= =================================================== + This table describes attributes that typically belong to objects of this class. + Since attributes are dynamically provided (see + :ref:`determine-available-attributes-of-an-object`), there is not a guarantee that + these attributes will always be present, nor is this list comprehensive in any way. + + =================== ======================================================== + Attribute Description + =================== ======================================================== + ``backgroundColor`` The background color of a widget, given as a hexadecimal + (``0x######``). + ``headerColor`` The header color of a widget, given as a hexadecimal + (``0x######``). + =================== ======================================================== + """ @@ -189,21 +187,20 @@ class Submenu(BaseList): **Typical Attributes** - This table describes attributes that typically belong to objects of this - class. Since attributes are dynamically provided (see - :ref:`determine-available-attributes-of-an-object`), there is not a - guarantee that these attributes will always be present, nor is this list - necessarily complete. - - ======================= =================================================== - Attribute Description - ======================= =================================================== - ``children`` A list of the :class:`.MenuLink`\ s in this - submenu. Can be iterated over by iterating over the - :class:`.Submenu` (e.g. ``for menu_link in - submenu``). - ``text`` The name of the submenu. - ======================= =================================================== + This table describes attributes that typically belong to objects of this class. + Since attributes are dynamically provided (see + :ref:`determine-available-attributes-of-an-object`), there is not a guarantee that + these attributes will always be present, nor is this list necessarily complete. + + ============ ===================================================================== + Attribute Description + ============ ===================================================================== + ``children`` A list of the :class:`.MenuLink`\ s in this submenu. Can be iterated + over by iterating over the :class:`.Submenu` (e.g. ``for menu_link in + submenu``). + ``text`` The name of the submenu. + ============ ===================================================================== + """ CHILD_ATTRIBUTE = "children" @@ -220,9 +217,9 @@ class SubredditWidgets(AsyncPRAWBase): widgets = subreddit.widgets Data will be lazy-loaded. By default, Async PRAW will not request progressively - loading images from Reddit. To enable this, instantiate a SubredditWidgets - object, then set the attribute ``progressive_images`` to ``True`` before - performing any action that would result in a network request. + loading images from Reddit. To enable this, instantiate a SubredditWidgets object, + then set the attribute ``progressive_images`` to ``True`` before performing any + action that would result in a network request. .. code-block:: python @@ -230,8 +227,8 @@ class SubredditWidgets(AsyncPRAWBase): widgets = subreddit.widgets widgets.progressive_images = True async for widget in widgets.sidebar(): - # do something - ... + # do something + ... Access a subreddit's widgets with the following attributes: @@ -242,26 +239,27 @@ class SubredditWidgets(AsyncPRAWBase): print([widget async for widget in widgets.sidebar()]) print([widget async for widget in widgets.topbar()]) - The attribute :attr:`.id_card` contains the subreddit's ID card, - which displays information like the number of subscribers. + The attribute :attr:`.id_card` contains the subreddit's ID card, which displays + information like the number of subscribers. - The attribute :attr:`.moderators_widget` contains the subreddit's - moderators widget, which lists the moderators of the subreddit. + The attribute :attr:`.moderators_widget` contains the subreddit's moderators widget, + which lists the moderators of the subreddit. - The attribute :attr:`.sidebar` contains a list of widgets which make up - the sidebar of the subreddit. + The attribute :attr:`.sidebar` contains a list of widgets which make up the sidebar + of the subreddit. - The attribute :attr:`.topbar` contains a list of widgets which make up - the top bar of the subreddit. + The attribute :attr:`.topbar` contains a list of widgets which make up the top bar + of the subreddit. - To edit a subreddit's widgets, use :attr:`~.SubredditWidgets.mod`. For - example: + To edit a subreddit's widgets, use :attr:`~.SubredditWidgets.mod`. For example: .. code-block:: python - await widgets.mod.add_text_area("My title", "**bold text**", - {"backgroundColor": "#FFFF66", - "headerColor": "#3333EE"}) + await widgets.mod.add_text_area( + "My title", + "**bold text**", + {"backgroundColor": "#FFFF66", "headerColor": "#3333EE"}, + ) For more information, see :class:`.SubredditWidgetsModeration`. @@ -312,9 +310,10 @@ def mod(self): .. note:: - Using any of the methods of :class:`.SubredditWidgetsModeration` - will likely result in the data of this :class:`.SubredditWidgets` - being outdated. To re-sync, call :meth:`.refresh`. + Using any of the methods of :class:`.SubredditWidgetsModeration` will likely + result in the data of this :class:`.SubredditWidgets` being outdated. To + re-sync, call :meth:`.refresh`. + """ return SubredditWidgetsModeration(self.subreddit, self._reddit) @@ -338,10 +337,9 @@ async def topbar(self): async def refresh(self): """Refresh the subreddit's widgets. - By default, Async PRAW will not request progressively - loading images from Reddit. To enable this, - set the attribute ``progressive_images`` to ``True`` prior to - calling ``refresh()``. + By default, Async PRAW will not request progressively loading images from + Reddit. To enable this, set the attribute ``progressive_images`` to ``True`` + prior to calling ``refresh()``. .. code-block:: python @@ -411,8 +409,9 @@ class SubredditWidgetsModeration: .. note:: - To use this class's methods, the authenticated user must be a moderator - with appropriate permissions. + To use this class's methods, the authenticated user must be a moderator with + appropriate permissions. + """ def __init__(self, subreddit, reddit): @@ -435,11 +434,11 @@ async def add_button_widget( :param short_name: A name for the widget, no longer than 30 characters. :param description: Markdown text to describe the widget. - :param buttons: A ``list`` of ``dict``\ s describing buttons, as - specified in `Reddit docs`_. As of this writing, the format is: + :param buttons: A ``list`` of ``dict``\ s describing buttons, as specified in + `Reddit docs`_. As of this writing, the format is: - Each button is either a text button or an image button. A text - button looks like this: + Each button is either a text button or an image button. A text button looks + like this: .. code-block:: text @@ -467,10 +466,9 @@ async def add_button_widget( "hoverState": {...} } - Both types of buttons have the field ``hoverState``. The field does - not have to be included (it is optional). If it is included, it can - be one of two types: text or image. A text ``hoverState`` looks - like this: + Both types of buttons have the field ``hoverState``. The field does not have + to be included (it is optional). If it is included, it can be one of two + types: text or image. A text ``hoverState`` looks like this: .. code-block:: text @@ -493,23 +491,21 @@ async def add_button_widget( "width": an integer } - .. note:: - The method :meth:`.upload_image` can be used to upload images to - Reddit for a ``url`` field that holds a Reddit-hosted image. + The method :meth:`.upload_image` can be used to upload images to Reddit + for a ``url`` field that holds a Reddit-hosted image. .. note:: - An image ``hoverState`` may be paired with a text widget, and a - text ``hoverState`` may be paired with an image widget. + An image ``hoverState`` may be paired with a text widget, and a text + ``hoverState`` may be paired with an image widget. - :param styles: A ``dict`` with keys ``backgroundColor`` and - ``headerColor``, and values of hex colors. For example, - ``{"backgroundColor": "#FFFF66", "headerColor": - "#3333EE"}``. + :param styles: A ``dict`` with keys ``backgroundColor`` and ``headerColor``, and + values of hex colors. For example, ``{"backgroundColor": "#FFFF66", + "headerColor": "#3333EE"}``. - .. _Reddit docs: https://www.reddit.com/dev/api#POST_api_widget + .. _reddit docs: https://www.reddit.com/dev/api#POST_api_widget Example usage: @@ -519,40 +515,35 @@ async def add_button_widget( widget_moderation = subreddit.widgets.mod my_image = await widget_moderation.upload_image("/path/to/pic.jpg") buttons = [ - { - "kind": "text", - "text": "View source", - "url": "https://github.com/praw-dev/praw", - "color": "#FF0000", - "textColor": "#00FF00", - "fillColor": "#0000FF", - "hoverState": { - "kind": "text", - "text": "ecruos weiV", - "color": "#FFFFFF", - "textColor": "#000000", - "fillColor": "#0000FF" - } - }, - { - "kind": "image", - "text": "View documentation", - "linkUrl": "https://praw.readthedocs.io", - "url": my_image, - "height": 200, - "width": 200, - "hoverState": { - "kind": "image", - "url": my_image, - "height": 200, - "width": 200 - } - } + { + "kind": "text", + "text": "View source", + "url": "https://github.com/praw-dev/praw", + "color": "#FF0000", + "textColor": "#00FF00", + "fillColor": "#0000FF", + "hoverState": { + "kind": "text", + "text": "ecruos weiV", + "color": "#FFFFFF", + "textColor": "#000000", + "fillColor": "#0000FF", + }, + }, + { + "kind": "image", + "text": "View documentation", + "linkUrl": "https://praw.readthedocs.io", + "url": my_image, + "height": 200, + "width": 200, + "hoverState": {"kind": "image", "url": my_image, "height": 200, "width": 200}, + }, ] styles = {"backgroundColor": "#FFFF66", "headerColor": "#3333EE"} new_widget = await widget_moderation.add_button_widget( - "Things to click", "Click some of these *cool* links!", - buttons, styles) + "Things to click", "Click some of these *cool* links!", buttons, styles + ) """ button_widget = { @@ -577,28 +568,29 @@ async def add_calendar( """Add and return a :class:`.Calendar` widget. :param short_name: A name for the widget, no longer than 30 characters. - :param google_calendar_id: An email-style calendar ID. To share a - Google Calendar, make it public, - then find the "Calendar ID." + :param google_calendar_id: An email-style calendar ID. To share a Google + Calendar, make it public, then find the "Calendar ID." :param requires_sync: A ``bool``. :param configuration: A ``dict`` as specified in `Reddit docs`_. - For example: + For example: + + .. code-block:: python - .. code-block:: python + { + "numEvents": 10, + "showDate": True, + "showDescription": False, + "showLocation": False, + "showTime": True, + "showTitle": True, + } - {"numEvents": 10, - "showDate": True, - "showDescription": False, - "showLocation": False, - "showTime": True, - "showTitle": True} - :param styles: A ``dict`` with keys ``backgroundColor`` and - ``headerColor``, and values of hex colors. For example, - ``{"backgroundColor": "#FFFF66", "headerColor": - "#3333EE"}``. + :param styles: A ``dict`` with keys ``backgroundColor`` and ``headerColor``, and + values of hex colors. For example, ``{"backgroundColor": "#FFFF66", + "headerColor": "#3333EE"}``. - .. _Reddit docs: https://www.reddit.com/dev/api#POST_api_widget + .. _reddit docs: https://www.reddit.com/dev/api#POST_api_widget Example usage: @@ -607,16 +599,19 @@ async def add_calendar( subreddit = await reddit.subreddit("mysub") widget_moderation = subreddit.widgets.mod styles = {"backgroundColor": "#FFFF66", "headerColor": "#3333EE"} - config = {"numEvents": 10, - "showDate": True, - "showDescription": False, - "showLocation": False, - "showTime": True, - "showTitle": True} + config = { + "numEvents": 10, + "showDate": True, + "showDescription": False, + "showLocation": False, + "showTime": True, + "showTitle": True, + } cal_id = "y6nm89jy427drk8l71w75w9wjn@group.calendar.google.com" - new_widget = await widget_moderation.add_calendar("Upcoming Events", - cal_id, True, - config, styles) + new_widget = await widget_moderation.add_calendar( + "Upcoming Events", cal_id, True, config, styles + ) + """ calendar = { "shortName": short_name, @@ -635,15 +630,13 @@ async def add_community_list( """Add and return a :class:`.CommunityList` widget. :param short_name: A name for the widget, no longer than 30 characters. - :param data: A ``list`` of subreddits. Subreddits can be represented as - ``str`` (e.g. the string ``"redditdev"``) or as - :class:`.Subreddit` (e.g. - ``reddit.subreddit("redditdev")``). These types may be - mixed within the list. - :param styles: A ``dict`` with keys ``backgroundColor`` and - ``headerColor``, and values of hex colors. For example, - ``{"backgroundColor": "#FFFF66", "headerColor": - "#3333EE"}``. + :param data: A ``list`` of subreddits. Subreddits can be represented as ``str`` + (e.g. the string ``"redditdev"``) or as :class:`.Subreddit` (e.g. + ``reddit.subreddit("redditdev")``). These types may be mixed within the + list. + :param styles: A ``dict`` with keys ``backgroundColor`` and ``headerColor``, and + values of hex colors. For example, ``{"backgroundColor": "#FFFF66", + "headerColor": "#3333EE"}``. :param description: A ``str`` containing Markdown (default: ``""``). Example usage: @@ -655,10 +648,9 @@ async def add_community_list( styles = {"backgroundColor": "#FFFF66", "headerColor": "#3333EE"} new_subreddit = await reddit.subreddit("redditdev") subreddits = ["learnpython", new_subreddit] - new_widget = await widget_moderation.add_community_list("My fav subs", - subreddits, - styles, - "description") + new_widget = await widget_moderation.add_community_list( + "My fav subs", subreddits, styles, "description" + ) """ community_list = { @@ -681,33 +673,41 @@ async def add_custom_widget( :param css: The CSS for the widget, no longer than 100000 characters. .. note:: - As of this writing, Reddit will not accept empty CSS. If you - wish to create a custom widget without CSS, consider using - ``"/**/"`` (an empty comment) as your CSS. + + As of this writing, Reddit will not accept empty CSS. If you wish to + create a custom widget without CSS, consider using ``"/**/"`` (an empty + comment) as your CSS. :param height: The height of the widget, between 50 and 500. - :param image_data: A ``list`` of ``dict``\ s as specified in - `Reddit docs`_. Each ``dict`` represents an image and has the - key ``"url"`` which maps to the URL of an image hosted on - Reddit's servers. Images should be uploaded using - :meth:`.upload_image`. + :param image_data: A ``list`` of ``dict``\ s as specified in `Reddit docs`_. + Each ``dict`` represents an image and has the key ``"url"`` which maps to + the URL of an image hosted on Reddit's servers. Images should be uploaded + using :meth:`.upload_image`. For example: .. code-block:: python - [{"url": "https://some.link", # from upload_image() - "width": 600, "height": 450, - "name": "logo"}, - {"url": "https://other.link", # from upload_image() - "width": 450, "height": 600, - "name": "icon"}] + [ + { + "url": "https://some.link", # from upload_image() + "width": 600, + "height": 450, + "name": "logo", + }, + { + "url": "https://other.link", # from upload_image() + "width": 450, + "height": 600, + "name": "icon", + }, + ] - :param styles: A ``dict`` with keys ``backgroundColor`` and - ``headerColor``, and values of hex colors. For example, - ``{"backgroundColor": "#FFFF66", "headerColor": "#3333EE"}``. + :param styles: A ``dict`` with keys ``backgroundColor`` and ``headerColor``, and + values of hex colors. For example, ``{"backgroundColor": "#FFFF66", + "headerColor": "#3333EE"}``. - .. _Reddit docs: https://www.reddit.com/dev/api#POST_api_widget + .. _reddit docs: https://www.reddit.com/dev/api#POST_api_widget Example usage: @@ -716,17 +716,15 @@ async def add_custom_widget( subreddit = await reddit.subreddit("mysub") widget_moderation = subreddit.widgets.mod image_paths = ["/path/to/image1.jpg", "/path/to/image2.png"] - image_urls = [widget_moderation.upload_image(img_path) - for img_path in image_paths] - image_dicts = [{"width": 600, "height": 450, "name": "logo", - "url": image_urls[0]}, - {"width": 450, "height": 600, "name": "icon", - "url": image_urls[1]}] + image_urls = [widget_moderation.upload_image(img_path) for img_path in image_paths] + image_dicts = [ + {"width": 600, "height": 450, "name": "logo", "url": image_urls[0]}, + {"width": 450, "height": 600, "name": "icon", "url": image_urls[1]}, + ] styles = {"backgroundColor": "#FFFF66", "headerColor": "#3333EE"} - new_widget = await widget_moderation.add_custom_widget("My widget", - "# Hello world!", - "/**/", 200, - image_dicts, styles) + new_widget = await widget_moderation.add_custom_widget( + "My widget", "# Hello world!", "/**/", 200, image_dicts, styles + ) """ custom_widget = { @@ -745,27 +743,34 @@ async def add_image_widget(self, short_name, data, styles, **other_settings): r"""Add and return an :class:`.ImageWidget`. :param short_name: A name for the widget, no longer than 30 characters. - :param data: A ``list`` of ``dict``\ s as specified in `Reddit docs`_. - Each ``dict`` has the key ``"url"`` which maps to the URL - of an image hosted on Reddit's servers. Images should - be uploaded using :meth:`.upload_image`. + :param data: A ``list`` of ``dict``\ s as specified in `Reddit docs`_. Each + ``dict`` has the key ``"url"`` which maps to the URL of an image hosted on + Reddit's servers. Images should be uploaded using :meth:`.upload_image`. For example: .. code-block:: python - [{"url": "https://some.link", # from upload_image() - "width": 600, "height": 450, - "linkUrl": "https://github.com/praw-dev/praw"}, - {"url": "https://other.link", # from upload_image() - "width": 450, "height": 600, - "linkUrl": "https://praw.readthedocs.io"}] + [ + { + "url": "https://some.link", # from upload_image() + "width": 600, + "height": 450, + "linkUrl": "https://github.com/praw-dev/praw", + }, + { + "url": "https://other.link", # from upload_image() + "width": 450, + "height": 600, + "linkUrl": "https://praw.readthedocs.io", + }, + ] - :param styles: A ``dict`` with keys ``backgroundColor`` and - ``headerColor``, and values of hex colors. For example, - ``{"backgroundColor": "#FFFF66", "headerColor": "#3333EE"}``. + :param styles: A ``dict`` with keys ``backgroundColor`` and ``headerColor``, and + values of hex colors. For example, ``{"backgroundColor": "#FFFF66", + "headerColor": "#3333EE"}``. - .. _Reddit docs: https://www.reddit.com/dev/api#POST_api_widget + .. _reddit docs: https://www.reddit.com/dev/api#POST_api_widget Example usage: @@ -774,12 +779,19 @@ async def add_image_widget(self, short_name, data, styles, **other_settings): subreddit = await reddit.subreddit("mysub") widget_moderation = subreddit.widgets.mod image_paths = ["/path/to/image1.jpg", "/path/to/image2.png"] - image_dicts = [{"width": 600, "height": 450, "linkUrl": "", - "url": widget_moderation.upload_image(img_path)} - for img_path in image_paths] + image_dicts = [ + { + "width": 600, + "height": 450, + "linkUrl": "", + "url": widget_moderation.upload_image(img_path), + } + for img_path in image_paths + ] styles = {"backgroundColor": "#FFFF66", "headerColor": "#3333EE"} - new_widget = await widget_moderation.add_image_widget("My cool pictures", - image_dicts, styles) + new_widget = await widget_moderation.add_image_widget( + "My cool pictures", image_dicts, styles + ) """ image_widget = { @@ -794,8 +806,8 @@ async def add_image_widget(self, short_name, data, styles, **other_settings): async def add_menu(self, data, **other_settings): r"""Add and return a :class:`.Menu` widget. - :param data: A ``list`` of ``dict``\ s describing menu contents, as - specified in `Reddit docs`_. As of this writing, the format is: + :param data: A ``list`` of ``dict``\ s describing menu contents, as specified in + `Reddit docs`_. As of this writing, the format is: .. code-block:: text @@ -820,7 +832,8 @@ async def add_menu(self, data, **other_settings): ... ] - .. _Reddit docs: https://www.reddit.com/dev/api#POST_api_widget + + .. _reddit docs: https://www.reddit.com/dev/api#POST_api_widget Example usage: @@ -829,13 +842,15 @@ async def add_menu(self, data, **other_settings): subreddit = await reddit.subreddit("mysub") widget_moderation = subreddit.widgets.mod menu_contents = [ - {"text": "My homepage", "url": "https://example.com"}, - {"text": "Python packages", - "children": [ - {"text": "PRAW", "url": "https://praw.readthedocs.io/"}, - {"text": "requests", "url": "http://python-requests.org"} - ]}, - {"text": "Reddit homepage", "url": "https://reddit.com"} + {"text": "My homepage", "url": "https://example.com"}, + { + "text": "Python packages", + "children": [ + {"text": "PRAW", "url": "https://praw.readthedocs.io/"}, + {"text": "requests", "url": "http://python-requests.org"}, + ], + }, + {"text": "Reddit homepage", "url": "https://reddit.com"}, ] new_widget = await widget_moderation.add_menu(menu_contents) @@ -851,17 +866,16 @@ async def add_post_flair_widget( :param short_name: A name for the widget, no longer than 30 characters. :param display: Display style. Either ``"cloud"`` or ``"list"``. - :param order: A ``list`` of flair template IDs. You can get all flair - template IDs in a subreddit with: + :param order: A ``list`` of flair template IDs. You can get all flair template + IDs in a subreddit with: .. code-block:: python flairs = [f["id"] for f in subreddit.flair.link_templates] - :param styles: A ``dict`` with keys ``backgroundColor`` and - ``headerColor``, and values of hex colors. For example, - ``{"backgroundColor": "#FFFF66", "headerColor": - "#3333EE"}``. + :param styles: A ``dict`` with keys ``backgroundColor`` and ``headerColor``, and + values of hex colors. For example, ``{"backgroundColor": "#FFFF66", + "headerColor": "#3333EE"}``. Example usage: @@ -871,9 +885,9 @@ async def add_post_flair_widget( widget_moderation = subreddit.widgets.mod flairs = [f["id"] async for f in subreddit.flair.link_templates] styles = {"backgroundColor": "#FFFF66", "headerColor": "#3333EE"} - new_widget = await widget_moderation.add_post_flair_widget("Some flairs", - "list", - flairs, styles) + new_widget = await widget_moderation.add_post_flair_widget( + "Some flairs", "list", flairs, styles + ) """ post_flair = { @@ -891,10 +905,9 @@ async def add_text_area(self, short_name, text, styles, **other_settings): :param short_name: A name for the widget, no longer than 30 characters. :param text: The Markdown text displayed in the widget. - :param styles: A ``dict`` with keys ``backgroundColor`` and - ``headerColor``, and values of hex colors. For example, - ``{"backgroundColor": "#FFFF66", "headerColor": - "#3333EE"}``. + :param styles: A ``dict`` with keys ``backgroundColor`` and ``headerColor``, and + values of hex colors. For example, ``{"backgroundColor": "#FFFF66", + "headerColor": "#3333EE"}``. Example usage: @@ -903,9 +916,9 @@ async def add_text_area(self, short_name, text, styles, **other_settings): subreddit = await reddit.subreddit("mysub") widget_moderation = subreddit.widgets.mod styles = {"backgroundColor": "#FFFF66", "headerColor": "#3333EE"} - new_widget = await widget_moderation.add_text_area("My cool title", - "*Hello* **world**!", - styles) + new_widget = await widget_moderation.add_text_area( + "My cool title", "*Hello* **world**!", styles + ) """ text_area = { @@ -920,9 +933,8 @@ async def add_text_area(self, short_name, text, styles, **other_settings): async def reorder(self, new_order, section="sidebar"): """Reorder the widgets. - :param new_order: A list of widgets. Represented as a ``list`` that - contains ``Widget`` objects, or widget IDs as strings. These types - may be mixed. + :param new_order: A list of widgets. Represented as a ``list`` that contains + ``Widget`` objects, or widget IDs as strings. These types may be mixed. :param section: The section to reorder. (default: ``"sidebar"``) Example usage: @@ -948,11 +960,12 @@ async def upload_image(self, file_path): """Upload an image to Reddit and get the URL. :param file_path: The path to the local file. + :returns: The URL of the uploaded image as a ``str``. - This method is used to upload images for widgets. For example, - it can be used in conjunction with :meth:`.add_image_widget`, - :meth:`.add_custom_widget`, and :meth:`.add_button_widget`. + This method is used to upload images for widgets. For example, it can be used in + conjunction with :meth:`.add_image_widget`, :meth:`.add_custom_widget`, and + :meth:`.add_button_widget`. Example usage: @@ -963,6 +976,7 @@ async def upload_image(self, file_path): images = [{"width": 300, "height": 300, "url": image_url, "linkUrl": ""}] styles = {"backgroundColor": "#FFFF66", "headerColor": "#3333EE"} await my_sub.widgets.mod.add_image_widget("My cool pictures", images, styles) + """ img_data = { "filepath": os.path.basename(file_path), @@ -996,9 +1010,11 @@ def mod(self): """Get an instance of :class:`.WidgetModeration` for this widget. .. note:: - Using any of the methods of :class:`.WidgetModeration` will likely - make outdated the data in the :class:`.SubredditWidgets` that this - widget belongs to. To remedy this, call :meth:`~.SubredditWidgets.refresh`. + + Using any of the methods of :class:`.WidgetModeration` will likely make + outdated the data in the :class:`.SubredditWidgets` that this widget belongs + to. To remedy this, call :meth:`~.SubredditWidgets.refresh`. + """ return WidgetModeration(self, self.subreddit, self._reddit) @@ -1042,34 +1058,34 @@ class ButtonWidget(Widget, BaseList): subreddit = await reddit.subreddit("redditdev") widgets = subreddit.widgets buttons = [ - { - "kind": "text", - "text": "View source", - "url": "https://github.com/praw-dev/praw", - "color": "#FF0000", - "textColor": "#00FF00", - "fillColor": "#0000FF", - "hoverState": { - "kind": "text", - "text": "ecruos weiV", - "color": "#000000", - "textColor": "#FFFFFF", - "fillColor": "#0000FF" - } - }, - { - "kind": "text", - "text": "View documentation", - "url": "https://praw.readthedocs.io", - "color": "#FFFFFF", - "textColor": "#FFFF00", - "fillColor": "#0000FF" - }, + { + "kind": "text", + "text": "View source", + "url": "https://github.com/praw-dev/praw", + "color": "#FF0000", + "textColor": "#00FF00", + "fillColor": "#0000FF", + "hoverState": { + "kind": "text", + "text": "ecruos weiV", + "color": "#000000", + "textColor": "#FFFFFF", + "fillColor": "#0000FF", + }, + }, + { + "kind": "text", + "text": "View documentation", + "url": "https://praw.readthedocs.io", + "color": "#FFFFFF", + "textColor": "#FFFF00", + "fillColor": "#0000FF", + }, ] styles = {"backgroundColor": "#FFFF66", "headerColor": "#3333EE"} button_widget = await widgets.mod.add_button_widget( - "Things to click", "Click some of these *cool* links!", - buttons, styles) + "Things to click", "Click some of these *cool* links!", buttons, styles + ) For more information on creation, see :meth:`.add_button_widget`. @@ -1078,8 +1094,9 @@ class ButtonWidget(Widget, BaseList): .. code-block:: python new_styles = {"backgroundColor": "#FFFFFF", "headerColor": "#FF9900"} - button_widget = await button_widget.mod.update(shortName="My fav buttons", - styles=new_styles) + button_widget = await button_widget.mod.update( + shortName="My fav buttons", styles=new_styles + ) Delete one (requires proper moderator permissions): @@ -1089,29 +1106,27 @@ class ButtonWidget(Widget, BaseList): **Typical Attributes** - This table describes attributes that typically belong to objects of this - class. Since attributes are dynamically provided (see - :ref:`determine-available-attributes-of-an-object`), there is not a - guarantee that these attributes will always be present, nor is this list - necessarily complete. - - ======================= =================================================== - Attribute Description - ======================= =================================================== - ``buttons`` A ``list`` of :class:`.Button`\ s. These can also - be accessed just by iterating over the - :class:`.ButtonWidget` (e.g. ``for button in - button_widget``). - ``description`` The description, in Markdown. - ``description_html`` The description, in HTML. - ``id`` The widget ID. - ``kind`` The widget kind (always ``"button"``). - ``shortName`` The short name of the widget. - ``styles`` A ``dict`` with the keys ``"backgroundColor"`` and - ``"headerColor"``. - ``subreddit`` The :class:`.Subreddit` the button widget belongs - to. - ======================= =================================================== + This table describes attributes that typically belong to objects of this class. + Since attributes are dynamically provided (see + :ref:`determine-available-attributes-of-an-object`), there is not a guarantee that + these attributes will always be present, nor is this list necessarily complete. + + ==================== ============================================================= + Attribute Description + ==================== ============================================================= + ``buttons`` A ``list`` of :class:`.Button`\ s. These can also be accessed + just by iterating over the :class:`.ButtonWidget` (e.g. ``for + button in button_widget``). + ``description`` The description, in Markdown. + ``description_html`` The description, in HTML. + ``id`` The widget ID. + ``kind`` The widget kind (always ``"button"``). + ``shortName`` The short name of the widget. + ``styles`` A ``dict`` with the keys ``"backgroundColor"`` and + ``"headerColor"``. + ``subreddit`` The :class:`.Subreddit` the button widget belongs to. + ==================== ============================================================= + """ CHILD_ATTRIBUTE = "buttons" @@ -1141,15 +1156,18 @@ class Calendar(Widget): subreddit = await reddit.subreddit("redditdev") widgets = subreddit.widgets styles = {"backgroundColor": "#FFFF66", "headerColor": "#3333EE"} - config = {"numEvents": 10, - "showDate": True, - "showDescription": False, - "showLocation": False, - "showTime": True, - "showTitle": True} + config = { + "numEvents": 10, + "showDate": True, + "showDescription": False, + "showLocation": False, + "showTime": True, + "showTitle": True, + } cal_id = "y6nm89jy427drk8l71w75w9wjn@group.calendar.google.com" calendar = await widgets.mod.add_calendar( - "Upcoming Events", cal_id, True, config, styles) + "Upcoming Events", cal_id, True, config, styles + ) For more information on creation, see :meth:`.add_calendar`. @@ -1168,26 +1186,25 @@ class Calendar(Widget): **Typical Attributes** - This table describes attributes that typically belong to objects of this - class. Since attributes are dynamically provided (see - :ref:`determine-available-attributes-of-an-object`), there is not a - guarantee that these attributes will always be present, nor is this list - necessarily complete. - - ======================= =================================================== - Attribute Description - ======================= =================================================== - ``configuration`` A ``dict`` describing the calendar configuration. - ``data`` A ``list`` of ``dict``\ s that represent events. - ``id`` The widget ID. - ``kind`` The widget kind (always ``"calendar"``). - ``requiresSync`` A ``bool``. - ``shortName`` The short name of the widget. - ``styles`` A ``dict`` with the keys ``"backgroundColor"`` and - ``"headerColor"``. - ``subreddit`` The :class:`.Subreddit` the button widget belongs - to. - ======================= =================================================== + This table describes attributes that typically belong to objects of this class. + Since attributes are dynamically provided (see + :ref:`determine-available-attributes-of-an-object`), there is not a guarantee that + these attributes will always be present, nor is this list necessarily complete. + + ================= ===================================================== + Attribute Description + ================= ===================================================== + ``configuration`` A ``dict`` describing the calendar configuration. + ``data`` A ``list`` of ``dict``\ s that represent events. + ``id`` The widget ID. + ``kind`` The widget kind (always ``"calendar"``). + ``requiresSync`` A ``bool``. + ``shortName`` The short name of the widget. + ``styles`` A ``dict`` with the keys ``"backgroundColor"`` and + ``"headerColor"``. + ``subreddit`` The :class:`.Subreddit` the button widget belongs to. + ================= ===================================================== + """ @@ -1217,9 +1234,9 @@ class CommunityList(Widget, BaseList): styles = {"backgroundColor": "#FFFF66", "headerColor": "#3333EE"} new_subreddit = await reddit.subreddit("announcements") subreddits = ["learnpython", new_subreddit] - community_list = await widgets.mod.add_community_list("Related subreddits", - subreddits, styles, - "description") + community_list = await widgets.mod.add_community_list( + "Related subreddits", subreddits, styles, "description" + ) For more information on creation, see :meth:`.add_community_list`. @@ -1228,8 +1245,9 @@ class CommunityList(Widget, BaseList): .. code-block:: python new_styles = {"backgroundColor": "#FFFFFF", "headerColor": "#FF9900"} - community_list = await community_list.mod.update(shortName="My fav subs", - styles=new_styles) + community_list = await community_list.mod.update( + shortName="My fav subs", styles=new_styles + ) Delete one (requires proper moderator permissions): @@ -1239,27 +1257,24 @@ class CommunityList(Widget, BaseList): **Typical Attributes** - This table describes attributes that typically belong to objects of this - class. Since attributes are dynamically provided (see - :ref:`determine-available-attributes-of-an-object`), there is not a - guarantee that these attributes will always be present, nor is this list - necessarily complete. - - ======================= =================================================== - Attribute Description - ======================= =================================================== - ``data`` A ``list`` of :class:`.Subreddit`\ s. These can - also be iterated over by iterating over the - :class:`.CommunityList` (e.g. ``for sub in - community_list``). - ``id`` The widget ID. - ``kind`` The widget kind (always ``"community-list"``). - ``shortName`` The short name of the widget. - ``styles`` A ``dict`` with the keys ``"backgroundColor"`` and - ``"headerColor"``. - ``subreddit`` The :class:`.Subreddit` the button widget belongs - to. - ======================= =================================================== + This table describes attributes that typically belong to objects of this class. + Since attributes are dynamically provided (see + :ref:`determine-available-attributes-of-an-object`), there is not a guarantee that + these attributes will always be present, nor is this list necessarily complete. + + ============= ===================================================================== + Attribute Description + ============= ===================================================================== + ``data`` A ``list`` of :class:`.Subreddit`\ s. These can also be iterated over + by iterating over the :class:`.CommunityList` (e.g. ``for sub in + community_list``). + ``id`` The widget ID. + ``kind`` The widget kind (always ``"community-list"``). + ``shortName`` The short name of the widget. + ``styles`` A ``dict`` with the keys ``"backgroundColor"`` and ``"headerColor"``. + ``subreddit`` The :class:`.Subreddit` the button widget belongs to. + ============= ===================================================================== + """ CHILD_ATTRIBUTE = "data" @@ -1291,7 +1306,8 @@ class CustomWidget(Widget): widgets = subreddit.widgets styles = {"backgroundColor": "#FFFF66", "headerColor": "#3333EE"} custom = await widgets.mod.add_custom_widget( - "My custom widget", "# Hello world!", "/**/", 200, [], styles) + "My custom widget", "# Hello world!", "/**/", 200, [], styles + ) For more information on creation, see :meth:`.add_custom_widget`. @@ -1310,30 +1326,28 @@ class CustomWidget(Widget): **Typical Attributes** - This table describes attributes that typically belong to objects of this - class. Since attributes are dynamically provided (see - :ref:`determine-available-attributes-of-an-object`), there is not a - guarantee that these attributes will always be present, nor is this list - necessarily complete. - - ======================= =================================================== - Attribute Description - ======================= =================================================== - ``css`` The CSS of the widget, as a ``str``. - ``height`` The height of the widget, as an ``int``. - ``id`` The widget ID. - ``imageData`` A ``list`` of :class:`.ImageData` that belong to - the widget. - ``kind`` The widget kind (always ``"custom"``). - ``shortName`` The short name of the widget. - ``styles`` A ``dict`` with the keys ``"backgroundColor"`` and - ``"headerColor"``. - ``stylesheetUrl`` A link to the widget's stylesheet. - ``subreddit`` The :class:`.Subreddit` the button widget belongs - to. - ``text`` The text contents, as Markdown. - ``textHtml`` The text contents, as HTML. - ======================= =================================================== + This table describes attributes that typically belong to objects of this class. + Since attributes are dynamically provided (see + :ref:`determine-available-attributes-of-an-object`), there is not a guarantee that + these attributes will always be present, nor is this list necessarily complete. + + ================= ============================================================ + Attribute Description + ================= ============================================================ + ``css`` The CSS of the widget, as a ``str``. + ``height`` The height of the widget, as an ``int``. + ``id`` The widget ID. + ``imageData`` A ``list`` of :class:`.ImageData` that belong to the widget. + ``kind`` The widget kind (always ``"custom"``). + ``shortName`` The short name of the widget. + ``styles`` A ``dict`` with the keys ``"backgroundColor"`` and + ``"headerColor"``. + ``stylesheetUrl`` A link to the widget's stylesheet. + ``subreddit`` The :class:`.Subreddit` the button widget belongs to. + ``text`` The text contents, as Markdown. + ``textHtml`` The text contents, as HTML. + ================= ============================================================ + """ def __init__(self, reddit, _data): @@ -1363,30 +1377,29 @@ class IDCard(Widget): **Typical Attributes** - This table describes attributes that typically belong to objects of this - class. Since attributes are dynamically provided (see - :ref:`determine-available-attributes-of-an-object`), there is not a - guarantee that these attributes will always be present, nor is this list - necessarily complete. - - =========================== =============================================== - Attribute Description - =========================== =============================================== - ``currentlyViewingCount`` The number of Redditors viewing the subreddit. - ``currentlyViewingText`` The text displayed next to the view count. For - example, "users online". - ``description`` The subreddit description. - ``id`` The widget ID. - ``kind`` The widget kind (always ``"id-card"``). - ``shortName`` The short name of the widget. - ``styles`` A ``dict`` with the keys ``"backgroundColor"`` - and ``"headerColor"``. - ``subreddit`` The :class:`.Subreddit` the button widget - belongs to. - ``subscribersCount`` The number of subscribers to the subreddit. - ``subscribersText`` The text displayed next to the subscriber - count. For example, "users subscribed". - =========================== =============================================== + This table describes attributes that typically belong to objects of this class. + Since attributes are dynamically provided (see + :ref:`determine-available-attributes-of-an-object`), there is not a guarantee that + these attributes will always be present, nor is this list necessarily complete. + + ========================= ======================================================= + Attribute Description + ========================= ======================================================= + ``currentlyViewingCount`` The number of Redditors viewing the subreddit. + ``currentlyViewingText`` The text displayed next to the view count. For example, + "users online". + ``description`` The subreddit description. + ``id`` The widget ID. + ``kind`` The widget kind (always ``"id-card"``). + ``shortName`` The short name of the widget. + ``styles`` A ``dict`` with the keys ``"backgroundColor"`` and + ``"headerColor"``. + ``subreddit`` The :class:`.Subreddit` the button widget belongs to. + ``subscribersCount`` The number of subscribers to the subreddit. + ``subscribersText`` The text displayed next to the subscriber count. For + example, "users subscribed". + ========================= ======================================================= + """ @@ -1415,12 +1428,19 @@ class ImageWidget(Widget, BaseList): subreddit = await reddit.subreddit("redditdev") widgets = subreddit.widgets image_paths = ["/path/to/image1.jpg", "/path/to/image2.png"] - image_dicts = [{"width": 600, "height": 450, "linkUrl": "", - "url": await widgets.mod.upload_image(img_path)} - for img_path in image_paths] + image_dicts = [ + { + "width": 600, + "height": 450, + "linkUrl": "", + "url": await widgets.mod.upload_image(img_path), + } + for img_path in image_paths + ] styles = {"backgroundColor": "#FFFF66", "headerColor": "#3333EE"} - image_widget = await widgets.mod.add_image_widget("My cool pictures", - image_dicts, styles) + image_widget = await widgets.mod.add_image_widget( + "My cool pictures", image_dicts, styles + ) For more information on creation, see :meth:`.add_image_widget`. @@ -1429,8 +1449,9 @@ class ImageWidget(Widget, BaseList): .. code-block:: python new_styles = {"backgroundColor": "#FFFFFF", "headerColor": "#FF9900"} - image_widget = await image_widget.mod.update(shortName="My fav images", - styles=new_styles) + image_widget = await image_widget.mod.update( + shortName="My fav images", styles=new_styles + ) Delete one (requires proper moderator permissions): @@ -1440,27 +1461,24 @@ class ImageWidget(Widget, BaseList): **Typical Attributes** - This table describes attributes that typically belong to objects of this - class. Since attributes are dynamically provided (see - :ref:`determine-available-attributes-of-an-object`), there is not a - guarantee that these attributes will always be present, nor is this list - necessarily complete. - - ======================= =================================================== - Attribute Description - ======================= =================================================== - ``data`` A list of the :class:`.Image`\ s in this widget. - Can be iterated over by iterating over the - :class:`.ImageWidget` (e.g. ``for img in - image_widget``). - ``id`` The widget ID. - ``kind`` The widget kind (always ``"image"``). - ``shortName`` The short name of the widget. - ``styles`` A ``dict`` with the keys ``"backgroundColor"`` and - ``"headerColor"``. - ``subreddit`` The :class:`.Subreddit` the button widget belongs - to. - ======================= =================================================== + This table describes attributes that typically belong to objects of this class. + Since attributes are dynamically provided (see + :ref:`determine-available-attributes-of-an-object`), there is not a guarantee that + these attributes will always be present, nor is this list necessarily complete. + + ============= ===================================================================== + Attribute Description + ============= ===================================================================== + ``data`` A list of the :class:`.Image`\ s in this widget. Can be iterated over + by iterating over the :class:`.ImageWidget` (e.g. ``for img in + image_widget``). + ``id`` The widget ID. + ``kind`` The widget kind (always ``"image"``). + ``shortName`` The short name of the widget. + ``styles`` A ``dict`` with the keys ``"backgroundColor"`` and ``"headerColor"``. + ``subreddit`` The :class:`.Subreddit` the button widget belongs to. + ============= ===================================================================== + """ CHILD_ATTRIBUTE = "data" @@ -1493,13 +1511,15 @@ class Menu(Widget, BaseList): subreddit = await reddit.subreddit("redditdev") widgets = subreddit.widgets menu_contents = [ - {"text": "My homepage", "url": "https://example.com"}, - {"text": "Python packages", - "children": [ - {"text": "PRAW", "url": "https://praw.readthedocs.io/"}, - {"text": "requests", "url": "http://python-requests.org"} - ]}, - {"text": "Reddit homepage", "url": "https://reddit.com"} + {"text": "My homepage", "url": "https://example.com"}, + { + "text": "Python packages", + "children": [ + {"text": "PRAW", "url": "https://praw.readthedocs.io/"}, + {"text": "requests", "url": "http://python-requests.org"}, + ], + }, + {"text": "Reddit homepage", "url": "https://reddit.com"}, ] menu = await widgets.mod.add_menu(menu_contents) @@ -1521,24 +1541,21 @@ class Menu(Widget, BaseList): **Typical Attributes** - This table describes attributes that typically belong to objects of this - class. Since attributes are dynamically provided (see - :ref:`determine-available-attributes-of-an-object`), there is not a - guarantee that these attributes will always be present, nor is this list - necessarily complete. - - ======================= =================================================== - Attribute Description - ======================= =================================================== - ``data`` A list of the :class:`.MenuLink`\ s and - :class:`.Submenu`\ s in this widget. - Can be iterated over by iterating over the - :class:`.Menu` (e.g. ``for item in menu``). - ``id`` The widget ID. - ``kind`` The widget kind (always ``"menu"``). - ``subreddit`` The :class:`.Subreddit` the button widget belongs - to. - ======================= =================================================== + This table describes attributes that typically belong to objects of this class. + Since attributes are dynamically provided (see + :ref:`determine-available-attributes-of-an-object`), there is not a guarantee that + these attributes will always be present, nor is this list necessarily complete. + + ============= ==================================================================== + Attribute Description + ============= ==================================================================== + ``data`` A list of the :class:`.MenuLink`\ s and :class:`.Submenu`\ s in this + widget. Can be iterated over by iterating over the :class:`.Menu` + (e.g. ``for item in menu``). + ``id`` The widget ID. + ``kind`` The widget kind (always ``"menu"``). + ``subreddit`` The :class:`.Subreddit` the button widget belongs to. + ============= ==================================================================== """ @@ -1564,27 +1581,24 @@ class ModeratorsWidget(Widget, BaseList): **Typical Attributes** - This table describes attributes that typically belong to objects of this - class. Since attributes are dynamically provided (see - :ref:`determine-available-attributes-of-an-object`), there is not a - guarantee that these attributes will always be present, nor is this list - necessarily complete. - - ======================= =================================================== - Attribute Description - ======================= =================================================== - ``id`` The widget ID. - ``kind`` The widget kind (always ``"moderators"``). - ``mods`` A list of the :class:`.Redditor`\ s that moderate - the subreddit. Can be iterated over by iterating - over the :class:`.ModeratorsWidget` (e.g. ``for - mod in widgets.moderators_widget``). - ``styles`` A ``dict`` with the keys ``"backgroundColor"`` - and ``"headerColor"``. - ``subreddit`` The :class:`.Subreddit` the button widget - belongs to. - ``totalMods`` The total number of moderators in the subreddit. - ======================= =================================================== + This table describes attributes that typically belong to objects of this class. + Since attributes are dynamically provided (see + :ref:`determine-available-attributes-of-an-object`), there is not a guarantee that + these attributes will always be present, nor is this list necessarily complete. + + ============= ===================================================================== + Attribute Description + ============= ===================================================================== + ``id`` The widget ID. + ``kind`` The widget kind (always ``"moderators"``). + ``mods`` A list of the :class:`.Redditor`\ s that moderate the subreddit. Can + be iterated over by iterating over the :class:`.ModeratorsWidget` + (e.g. ``for mod in widgets.moderators_widget``). + ``styles`` A ``dict`` with the keys ``"backgroundColor"`` and ``"headerColor"``. + ``subreddit`` The :class:`.Subreddit` the button widget belongs to. + ``totalMods`` The total number of moderators in the subreddit. + ============= ===================================================================== + """ CHILD_ATTRIBUTE = "mods" @@ -1624,8 +1638,9 @@ class PostFlairWidget(Widget, BaseList): widgets = subreddit.widgets flairs = [f["id"] async for f in subreddit.flair.link_templates] styles = {"backgroundColor": "#FFFF66", "headerColor": "#3333EE"} - post_flair = await widgets.mod.add_post_flair_widget("Some flairs", "list", - flairs, styles) + post_flair = await widgets.mod.add_post_flair_widget( + "Some flairs", "list", flairs, styles + ) For more information on creation, see :meth:`.add_post_flair_widget`. @@ -1644,31 +1659,26 @@ class PostFlairWidget(Widget, BaseList): **Typical Attributes** - This table describes attributes that typically belong to objects of this - class. Since attributes are dynamically provided (see - :ref:`determine-available-attributes-of-an-object`), there is not a - guarantee that these attributes will always be present, nor is this list - necessarily complete. - - ======================= =================================================== - Attribute Description - ======================= =================================================== - ``display`` The display style of the widget, either ``"cloud"`` - or ``"list"``. - ``id`` The widget ID. - ``kind`` The widget kind (always ``"post-flair"``). - ``order`` A list of the flair IDs in this widget. - Can be iterated over by iterating over the - :class:`.PostFlairWidget` (e.g. ``for flair_id in - post_flair``). - ``shortName`` The short name of the widget. - ``styles`` A ``dict`` with the keys ``"backgroundColor"`` and - ``"headerColor"``. - ``subreddit`` The :class:`.Subreddit` the button widget belongs - to. - ``templates`` A ``dict`` that maps flair IDs to ``dict``\ s that - describe flairs. - ======================= =================================================== + This table describes attributes that typically belong to objects of this class. + Since attributes are dynamically provided (see + :ref:`determine-available-attributes-of-an-object`), there is not a guarantee that + these attributes will always be present, nor is this list necessarily complete. + + ============= ===================================================================== + Attribute Description + ============= ===================================================================== + ``display`` The display style of the widget, either ``"cloud"`` or ``"list"``. + ``id`` The widget ID. + ``kind`` The widget kind (always ``"post-flair"``). + ``order`` A list of the flair IDs in this widget. Can be iterated over by + iterating over the :class:`.PostFlairWidget` (e.g. ``for flair_id in + post_flair``). + ``shortName`` The short name of the widget. + ``styles`` A ``dict`` with the keys ``"backgroundColor"`` and ``"headerColor"``. + ``subreddit`` The :class:`.Subreddit` the button widget belongs to. + ``templates`` A ``dict`` that maps flair IDs to ``dict``\ s that describe flairs. + ============= ===================================================================== + """ CHILD_ATTRIBUTE = "order" @@ -1686,41 +1696,39 @@ class RulesWidget(Widget, BaseList): if isinstance(widget, praw.models.RulesWidget): rules_widget = widget break - from pprint import pprint; pprint(rules_widget.data) + from pprint import pprint + + pprint(rules_widget.data) Update one (requires proper moderator permissions): .. code-block:: python new_styles = {"backgroundColor": "#FFFFFF", "headerColor": "#FF9900"} - await rules_widget.mod.update(display="compact", shortName="The LAWS", - styles=new_styles) + await rules_widget.mod.update( + display="compact", shortName="The LAWS", styles=new_styles + ) **Typical Attributes** - This table describes attributes that typically belong to objects of this - class. Since attributes are dynamically provided (see - :ref:`determine-available-attributes-of-an-object`), there is not a - guarantee that these attributes will always be present, nor is this list - necessarily complete. - - ======================= =================================================== - Attribute Description - ======================= =================================================== - ``data`` A list of the subreddit rules. - Can be iterated over by iterating over the - :class:`.RulesWidget` (e.g. ``for rule in - rules_widget``). - ``display`` The display style of the widget, either ``"full"`` - or ``"compact"``. - ``id`` The widget ID. - ``kind`` The widget kind (always ``"subreddit-rules"``). - ``shortName`` The short name of the widget. - ``styles`` A ``dict`` with the keys ``"backgroundColor"`` - and ``"headerColor"``. - ``subreddit`` The :class:`.Subreddit` the button widget - belongs to. - ======================= =================================================== + This table describes attributes that typically belong to objects of this class. + Since attributes are dynamically provided (see + :ref:`determine-available-attributes-of-an-object`), there is not a guarantee that + these attributes will always be present, nor is this list necessarily complete. + + ============= ===================================================================== + Attribute Description + ============= ===================================================================== + ``data`` A list of the subreddit rules. Can be iterated over by iterating over + the :class:`.RulesWidget` (e.g. ``for rule in rules_widget``). + ``display`` The display style of the widget, either ``"full"`` or ``"compact"``. + ``id`` The widget ID. + ``kind`` The widget kind (always ``"subreddit-rules"``). + ``shortName`` The short name of the widget. + ``styles`` A ``dict`` with the keys ``"backgroundColor"`` and ``"headerColor"``. + ``subreddit`` The :class:`.Subreddit` the button widget belongs to. + ============= ===================================================================== + """ CHILD_ATTRIBUTE = "data" @@ -1756,9 +1764,9 @@ class TextArea(Widget): subreddit = await reddit.subreddit("redditdev") widgets = subreddit.widgets styles = {"backgroundColor": "#FFFF66", "headerColor": "#3333EE"} - text_area = await widgets.mod.add_text_area("My cool title", - "*Hello* **world**!", - styles) + text_area = await widgets.mod.add_text_area( + "My cool title", "*Hello* **world**!", styles + ) For more information on creation, see :meth:`.add_text_area`. @@ -1767,8 +1775,7 @@ class TextArea(Widget): .. code-block:: python new_styles = {"backgroundColor": "#FFFFFF", "headerColor": "#FF9900"} - text_area = await text_area.mod.update(shortName="My fav text", - styles=new_styles) + text_area = await text_area.mod.update(shortName="My fav text", styles=new_styles) Delete one (requires proper moderator permissions): @@ -1778,25 +1785,23 @@ class TextArea(Widget): **Typical Attributes** - This table describes attributes that typically belong to objects of this - class. Since attributes are dynamically provided (see - :ref:`determine-available-attributes-of-an-object`), there is not a - guarantee that these attributes will always be present, nor is this list - necessarily complete. - - ======================= =================================================== - Attribute Description - ======================= =================================================== - ``id`` The widget ID. - ``kind`` The widget kind (always ``"textarea"``). - ``shortName`` The short name of the widget. - ``styles`` A ``dict`` with the keys ``"backgroundColor"`` and - ``"headerColor"``. - ``subreddit`` The :class:`.Subreddit` the button widget belongs - to. - ``text`` The widget's text, as Markdown. - ``textHtml`` The widget's text, as HTML. - ======================= =================================================== + This table describes attributes that typically belong to objects of this class. + Since attributes are dynamically provided (see + :ref:`determine-available-attributes-of-an-object`), there is not a guarantee that + these attributes will always be present, nor is this list necessarily complete. + + ============= ===================================================================== + Attribute Description + ============= ===================================================================== + ``id`` The widget ID. + ``kind`` The widget kind (always ``"textarea"``). + ``shortName`` The short name of the widget. + ``styles`` A ``dict`` with the keys ``"backgroundColor"`` and ``"headerColor"``. + ``subreddit`` The :class:`.Subreddit` the button widget belongs to. + ``text`` The widget's text, as Markdown. + ``textHtml`` The widget's text, as HTML. + ============= ===================================================================== + """ @@ -1824,6 +1829,7 @@ class WidgetModeration: widget = sidebar[0] await widget.mod.update(shortName="My new title") await widget.mod.delete() + """ def __init__(self, widget, subreddit, reddit): @@ -1840,6 +1846,7 @@ async def delete(self): .. code-block:: python await widget.mod.delete() + """ path = API_PATH["widget_modify"].format( widget_id=self.widget.id, subreddit=self._subreddit @@ -1849,10 +1856,9 @@ async def delete(self): async def update(self, **kwargs): """Update the widget. Returns the updated widget. - Parameters differ based on the type of widget. See - `Reddit documentation - `_ or the - document of the particular type of widget. + Parameters differ based on the type of widget. See `Reddit documentation + `_ or the document of + the particular type of widget. For example, update a text widget like so: @@ -1862,8 +1868,9 @@ async def update(self, **kwargs): .. note:: - Most parameters follow the ``lowerCamelCase`` convention. When in - doubt, check the Reddit documentation linked above. + Most parameters follow the ``lowerCamelCase`` convention. When in doubt, + check the Reddit documentation linked above. + """ path = API_PATH["widget_modify"].format( widget_id=self.widget.id, subreddit=self._subreddit diff --git a/asyncpraw/models/reddit/wikipage.py b/asyncpraw/models/reddit/wikipage.py index 865058f8e..17e49e173 100644 --- a/asyncpraw/models/reddit/wikipage.py +++ b/asyncpraw/models/reddit/wikipage.py @@ -14,14 +14,14 @@ class WikiPageModeration: """Provides a set of moderation functions for a WikiPage. - For example, to add ``spez`` as an editor on the wikipage ``praw_test`` - try: + For example, to add ``spez`` as an editor on the wikipage ``praw_test`` try: .. code-block:: python subreddit = await reddit.subreddit("test") page = await subreddit.wiki.get_page("praw_test") await page.mod.add("spez") + """ def __init__(self, wikipage: "WikiPage"): @@ -35,8 +35,8 @@ def __init__(self, wikipage: "WikiPage"): async def add(self, redditor: "asyncpraw.models.Redditor"): """Add an editor to this WikiPage. - :param redditor: A redditor name (e.g., ``"spez"``) or - :class:`~.Redditor` instance. + :param redditor: A redditor name (e.g., ``"spez"``) or :class:`~.Redditor` + instance. To add ``"spez"`` as an editor on the wikipage ``"praw_test"`` try: @@ -56,8 +56,8 @@ async def add(self, redditor: "asyncpraw.models.Redditor"): async def remove(self, redditor: "asyncpraw.models.Redditor"): """Remove an editor from this WikiPage. - :param redditor: A redditor name (e.g., ``"spez"``) or - :class:`~.Redditor` instance. + :param redditor: A redditor name (e.g., ``"spez"``) or :class:`~.Redditor` + instance. To remove ``"spez"`` as an editor on the wikipage ``"praw_test"`` try: @@ -89,14 +89,14 @@ async def update( :param listed: (boolean) Show this page on page list. :param permlevel: (int) Who can edit this page? (0) use subreddit wiki - permissions, (1) only approved wiki contributors for this page may - edit (see :meth:`.WikiPageModeration.add`), (2) only mods may edit - and view + permissions, (1) only approved wiki contributors for this page may edit (see + :meth:`.WikiPageModeration.add`), (2) only mods may edit and view :param other_settings: Additional keyword arguments to pass. + :returns: The updated WikiPage settings. - To set the wikipage ``praw_test`` in ``r/test`` to mod only and - disable it from showing in the page list, try: + To set the wikipage ``praw_test`` in ``r/test`` to mod only and disable it from + showing in the page list, try: .. code-block:: python @@ -118,27 +118,27 @@ class WikiPage(RedditBase): **Typical Attributes** - This table describes attributes that typically belong to objects of this - class. Since attributes are dynamically provided (see - :ref:`determine-available-attributes-of-an-object`), there is not a - guarantee that these attributes will always be present, nor is this list - necessarily complete. - - ======================= =================================================== - Attribute Description - ======================= =================================================== - ``content_html`` The contents of the wiki page, as HTML. - ``content_md`` The contents of the wiki page, as Markdown. - ``may_revise`` A ``bool`` representing whether or not the - authenticated user may edit the wiki page. - ``name`` The name of the wiki page. - ``revision_by`` The :class:`~.Redditor` who authored this - revision of the wiki page. - ``revision_date`` The time of this revision, in `Unix Time`_. - ``subreddit`` The :class:`~.Subreddit` this wiki page belongs to. - ======================= =================================================== - - .. _Unix Time: https://en.wikipedia.org/wiki/Unix_time + This table describes attributes that typically belong to objects of this class. + Since attributes are dynamically provided (see + :ref:`determine-available-attributes-of-an-object`), there is not a guarantee that + these attributes will always be present, nor is this list necessarily complete. + + ================= ================================================================= + Attribute Description + ================= ================================================================= + ``content_html`` The contents of the wiki page, as HTML. + ``content_md`` The contents of the wiki page, as Markdown. + ``may_revise`` A ``bool`` representing whether or not the authenticated user may + edit the wiki page. + ``name`` The name of the wiki page. + ``revision_by`` The :class:`~.Redditor` who authored this revision of the wiki + page. + ``revision_date`` The time of this revision, in `Unix Time`_. + ``subreddit`` The :class:`~.Subreddit` this wiki page belongs to. + ================= ================================================================= + + .. _unix time: https://en.wikipedia.org/wiki/Unix_time + """ __hash__ = RedditBase.__hash__ @@ -167,8 +167,7 @@ async def _revision_generator( def mod(self) -> WikiPageModeration: """Provide an instance of :class:`.WikiPageModeration`. - For example, to add ``spez`` as an editor on the wikipage ``praw_test`` - try: + For example, to add ``spez`` as an editor on the wikipage ``praw_test`` try: .. code-block:: python @@ -189,8 +188,8 @@ def __init__( ): """Construct an instance of the WikiPage object. - :param revision: A specific revision ID to fetch. By default, fetches - the most recent revision. + :param revision: A specific revision ID to fetch. By default, fetches the most + recent revision. """ self.name = name @@ -240,8 +239,8 @@ async def edit( :param reason: (Optional) The reason for the revision. :param other_settings: Additional keyword arguments to pass. - For example, to replace the first wiki page of ``r/test`` with the - phrase ``test wiki page``: + For example, to replace the first wiki page of ``r/test`` with the phrase ``test + wiki page``: .. code-block:: python diff --git a/asyncpraw/models/redditors.py b/asyncpraw/models/redditors.py index 11d232321..d663bdd39 100644 --- a/asyncpraw/models/redditors.py +++ b/asyncpraw/models/redditors.py @@ -30,6 +30,7 @@ def new( Additional keyword arguments are passed in the initialization of :class:`.ListingGenerator`. + """ return ListingGenerator(self._reddit, API_PATH["users_new"], **generator_kwargs) @@ -42,6 +43,7 @@ def popular( Additional keyword arguments are passed in the initialization of :class:`.ListingGenerator`. + """ return ListingGenerator( self._reddit, API_PATH["users_popular"], **generator_kwargs @@ -58,6 +60,7 @@ def search( Additional keyword arguments are passed in the initialization of :class:`.ListingGenerator`. + """ self._safely_add_arguments(generator_kwargs, "params", q=query) return ListingGenerator( @@ -69,12 +72,13 @@ def stream( ) -> AsyncIterator["asyncpraw.models.Subreddit"]: """Yield new Redditors as they are created. - Redditors are yielded oldest first. Up to 100 historical Redditors - will initially be returned. + Redditors are yielded oldest first. Up to 100 historical Redditors will + initially be returned. Keyword arguments are passed to :func:`.stream_generator`. :returns: Redditor profiles, which are a type of :class:`.Subreddit`. + """ return stream_generator(self.new, **stream_options) @@ -84,11 +88,13 @@ async def partial_redditors( """Get user summary data by redditor IDs. :param ids: An iterable of redditor fullname IDs. + :returns: A iterator producing types.SimpleNamespace objects. Each ID must be prefixed with ``t2_``. Invalid IDs are ignored by the server. + """ iterable = iter(ids) while True: diff --git a/asyncpraw/models/stylesheet.py b/asyncpraw/models/stylesheet.py index a6b457b5f..20366af03 100644 --- a/asyncpraw/models/stylesheet.py +++ b/asyncpraw/models/stylesheet.py @@ -8,16 +8,16 @@ class Stylesheet(AsyncPRAWBase): **Typical Attributes** - This table describes attributes that typically belong to objects of this - class. Since attributes are dynamically provided (see - :ref:`determine-available-attributes-of-an-object`), there is not a - guarantee that these attributes will always be present, nor is this list - necessarily complete. + This table describes attributes that typically belong to objects of this class. + Since attributes are dynamically provided (see + :ref:`determine-available-attributes-of-an-object`), there is not a guarantee that + these attributes will always be present, nor is this list necessarily complete. + + ============== ============================================ + Attribute Description + ============== ============================================ + ``images`` A ``list`` of images used by the stylesheet. + ``stylesheet`` The contents of the stylesheet, as CSS. + ============== ============================================ - ======================= =================================================== - Attribute Description - ======================= =================================================== - ``images`` A ``list`` of images used by the stylesheet. - ``stylesheet`` The contents of the stylesheet, as CSS. - ======================= =================================================== """ diff --git a/asyncpraw/models/subreddits.py b/asyncpraw/models/subreddits.py index e65d5c4b0..f57cb7362 100644 --- a/asyncpraw/models/subreddits.py +++ b/asyncpraw/models/subreddits.py @@ -26,6 +26,7 @@ def default( Additional keyword arguments are passed in the initialization of :class:`.ListingGenerator`. + """ return ListingGenerator( self._reddit, API_PATH["subreddits_default"], **generator_kwargs @@ -47,6 +48,7 @@ def premium( Additional keyword arguments are passed in the initialization of :class:`.ListingGenerator`. + """ return ListingGenerator( self._reddit, API_PATH["subreddits_gold"], **generator_kwargs @@ -59,6 +61,7 @@ def new( Additional keyword arguments are passed in the initialization of :class:`.ListingGenerator`. + """ return ListingGenerator( self._reddit, API_PATH["subreddits_new"], **generator_kwargs @@ -71,6 +74,7 @@ def popular( Additional keyword arguments are passed in the initialization of :class:`.ListingGenerator`. + """ return ListingGenerator( self._reddit, API_PATH["subreddits_popular"], **generator_kwargs @@ -85,11 +89,9 @@ async def recommended( ) -> List["asyncpraw.models.Subreddit"]: """Return subreddits recommended for the given list of subreddits. - :param subreddits: A list of Subreddit instances and/or subreddit - names. - :param omit_subreddits: A list of Subreddit instances and/or subreddit - names to exclude from the results (Reddit's end may not work as - expected). + :param subreddits: A list of Subreddit instances and/or subreddit names. + :param omit_subreddits: A list of Subreddit instances and/or subreddit names to + exclude from the results (Reddit's end may not work as expected). """ if not isinstance(subreddits, list): @@ -116,7 +118,9 @@ def search( Additional keyword arguments are passed in the initialization of :class:`.ListingGenerator`. - .. seealso:: :meth:`~.search_by_name` to search by subreddit names + .. seealso:: + + :meth:`~.search_by_name` to search by subreddit names """ self._safely_add_arguments(generator_kwargs, "params", q=query) @@ -167,8 +171,8 @@ def stream( ) -> AsyncIterator["asyncpraw.models.Subreddit"]: """Yield new subreddits as they are created. - Subreddits are yielded oldest first. Up to 100 historical subreddits - will initially be returned. + Subreddits are yielded oldest first. Up to 100 historical subreddits will + initially be returned. Keyword arguments are passed to :func:`.stream_generator`. diff --git a/asyncpraw/models/trophy.py b/asyncpraw/models/trophy.py index 393702302..846e96d1e 100644 --- a/asyncpraw/models/trophy.py +++ b/asyncpraw/models/trophy.py @@ -10,37 +10,35 @@ class Trophy(AsyncPRAWBase): """Represent a trophy. - End users should not instantiate this class directly. - :meth:`.Redditor.trophies` can be used to get a list - of the redditor's trophies. - + End users should not instantiate this class directly. :meth:`.Redditor.trophies` can + be used to get a list of the redditor's trophies. **Typical Attributes** - This table describes attributes that typically belong to objects of this - class. Since attributes are dynamically provided (see - :ref:`determine-available-attributes-of-an-object`), there is not a - guarantee that these attributes will always be present, nor is this list - necessarily complete. - - ======================= =================================================== - Attribute Description - ======================= =================================================== - ``award_id`` The ID of the trophy (sometimes ``None``). - ``description`` The description of the trophy (sometimes ``None``). - ``icon_40`` The URL of a 41x41 px icon for the trophy. - ``icon_70`` The URL of a 71x71 px icon for the trophy. - ``name`` The name of the trophy. - ``url`` A relevant URL (sometimes ``None``). - ======================= =================================================== + This table describes attributes that typically belong to objects of this class. + Since attributes are dynamically provided (see + :ref:`determine-available-attributes-of-an-object`), there is not a guarantee that + these attributes will always be present, nor is this list necessarily complete. + + =============== =================================================== + Attribute Description + =============== =================================================== + ``award_id`` The ID of the trophy (sometimes ``None``). + ``description`` The description of the trophy (sometimes ``None``). + ``icon_40`` The URL of a 41x41 px icon for the trophy. + ``icon_70`` The URL of a 71x71 px icon for the trophy. + ``name`` The name of the trophy. + ``url`` A relevant URL (sometimes ``None``). + =============== =================================================== + """ def __init__(self, reddit: "asyncpraw.Reddit", _data: Dict[str, Any]): """Initialize a Trophy instance. :param reddit: An instance of :class:`.Reddit`. - :param _data: The structured data, assumed to be a dict - and key ``"name"`` must be provided. + :param _data: The structured data, assumed to be a dict and key ``"name"`` must + be provided. """ assert isinstance(_data, dict) and "name" in _data diff --git a/asyncpraw/models/user.py b/asyncpraw/models/user.py index b4517d567..32e765219 100644 --- a/asyncpraw/models/user.py +++ b/asyncpraw/models/user.py @@ -26,26 +26,24 @@ def preferences(self) -> "asyncpraw.models.Preferences": .. code-block:: python - preferences = await reddit.user.preferences() - print(preferences["show_link_flair"]) + preferences = await reddit.user.preferences() + print(preferences["show_link_flair"]) Preferences can be updated via: .. code-block:: python - await reddit.user.preferences.update(show_link_flair=True) + await reddit.user.preferences.update(show_link_flair=True) - The :meth:`.Preferences.update` method returns the new state of the - preferences as a ``dict``, which can be used to check whether a - change went through. Changes with invalid types or parameter names - fail silently. + The :meth:`.Preferences.update` method returns the new state of the preferences + as a ``dict``, which can be used to check whether a change went through. Changes + with invalid types or parameter names fail silently. .. code-block:: python - original_preferences = await reddit.user.preferences() - new_prefs = await original_preferences.update(invalid_param=123) - print(original_preferences == new_prefs) # True, no change - + original_preferences = await reddit.user.preferences() + new_prefs = await original_preferences.update(invalid_param=123) + print(original_preferences == new_prefs) # True, no change """ return Preferences(self._reddit) @@ -82,12 +80,15 @@ async def friends( ) -> Union[List["asyncpraw.models.Redditor"], "asyncpraw.models.Redditor"]: """Return a RedditorList of friends or a Redditor in the friends list. - :param user: Checks to see if you are friends with the Redditor. Either - an instance of :class:`.Redditor` or a string can be given. - :returns: A list of Redditors, or a Redditor if you are friends with - the given Redditor. The Redditor also has friend attributes. - :raises: An instance of ``asyncprawcore.exceptions.BadRequest`` if you - are not friends with the specified Redditor. + :param user: Checks to see if you are friends with the Redditor. Either an + instance of :class:`.Redditor` or a string can be given. + + :returns: A list of Redditors, or a Redditor if you are friends with the given + Redditor. The Redditor also has friend attributes. + + :raises: An instance of ``asyncprawcore.exceptions.BadRequest`` if you are not + friends with the specified Redditor. + """ endpoint = ( API_PATH["friends"] @@ -99,13 +100,16 @@ async def friends( async def karma(self) -> Dict["asyncpraw.models.Subreddit", Dict[str, int]]: """Return a dictionary mapping subreddits to their karma. - The returned dict contains subreddits as keys. Each subreddit key - contains a sub-dict that have keys for ``comment_karma`` and - ``link_karma``. The dict is sorted in descending karma order. + The returned dict contains subreddits as keys. Each subreddit key contains a + sub-dict that have keys for ``comment_karma`` and ``link_karma``. The dict is + sorted in descending karma order. + + .. note:: + + Each key of the main dict is an instance of :class:`~.Subreddit`. It is + recommended to iterate over the dict in order to retrieve the values, + preferably through ``dict.items()``. - .. note:: Each key of the main dict is an instance of - :class:`~.Subreddit`. It is recommended to iterate over the dict in - order to retrieve the values, preferably through ``dict.items()``. """ karma_map = {} response = await self._reddit.get(API_PATH["karma"]) @@ -123,9 +127,11 @@ async def me( :param use_cache: When true, and if this function has been previously called, returned the cached version (default: True). - .. note:: If you change the Reddit instance's authorization, you might - want to refresh the cached value. Prefer using separate Reddit - instances, however, for distinct authorizations. + .. note:: + + If you change the Reddit instance's authorization, you might want to refresh + the cached value. Prefer using separate Reddit instances, however, for + distinct authorizations. .. deprecated:: 7.2 diff --git a/asyncpraw/models/util.py b/asyncpraw/models/util.py index 4521214d0..9391f33b8 100644 --- a/asyncpraw/models/util.py +++ b/asyncpraw/models/util.py @@ -9,6 +9,7 @@ class BoundedSet: """A set with a maximum size that evicts the oldest items when necessary. This class does not implement the complete set interface. + """ def __init__(self, max_items: int): @@ -44,6 +45,7 @@ def __init__(self, max_counter: int): .. note:: The computed value may be 3.125% higher due to jitter. + """ self._base = 1 self._max = max_counter @@ -65,15 +67,13 @@ def permissions_string( ) -> str: """Return a comma separated string of permission changes. - :param permissions: A list of strings, or ``None``. These strings can - exclusively contain ``+`` or ``-`` prefixes, or contain no prefixes at - all. When prefixed, the resulting string will simply be the joining of - these inputs. When not prefixed, all permissions are considered to be - additions, and all permissions in the ``known_permissions`` set that - aren't provided are considered to be removals. When ``None``, the result is - ``"+all"``. - :param known_permissions: A set of strings representing the available - permissions. + :param permissions: A list of strings, or ``None``. These strings can exclusively + contain ``+`` or ``-`` prefixes, or contain no prefixes at all. When prefixed, + the resulting string will simply be the joining of these inputs. When not + prefixed, all permissions are considered to be additions, and all permissions in + the ``known_permissions`` set that aren't provided are considered to be + removals. When ``None``, the result is ``"+all"``. + :param known_permissions: A set of strings representing the available permissions. """ if permissions is None: @@ -97,32 +97,29 @@ async def stream_generator( """Yield new items from ListingGenerators and ``None`` when paused. :param function: A callable that returns a ListingGenerator, e.g. - ``subreddit.comments`` or ``subreddit.new``. - - :param pause_after: An integer representing the number of requests that - result in no new items before this function yields ``None``, - effectively introducing a pause into the stream. A negative value - yields ``None`` after items from a single response have been yielded, - regardless of number of new items obtained in that response. A value of - ``0`` yields ``None`` after every response resulting in no new items, - and a value of ``None`` never introduces a pause (default: None). - - :param skip_existing: When True does not yield any results from the first - request thereby skipping any items that existed in the stream prior to - starting the stream (default: False). - + ``subreddit.comments`` or ``subreddit.new``. + :param pause_after: An integer representing the number of requests that result in no + new items before this function yields ``None``, effectively introducing a pause + into the stream. A negative value yields ``None`` after items from a single + response have been yielded, regardless of number of new items obtained in that + response. A value of ``0`` yields ``None`` after every response resulting in no + new items, and a value of ``None`` never introduces a pause (default: None). + :param skip_existing: When True does not yield any results from the first request + thereby skipping any items that existed in the stream prior to starting the + stream (default: False). :param attribute_name: The field to use as an id (default: "fullname"). - - :param exclude_before: When True does not pass ``params`` to ``functions`` - (default: False). + :param exclude_before: When True does not pass ``params`` to ``functions`` (default: + False). Additional keyword arguments will be passed to ``function``. - .. note:: This function internally uses an exponential delay with jitter - between subsequent responses that contain no new results, up to a - maximum delay of just over a 16 seconds. In practice that means that the - time before pause for ``pause_after=N+1`` is approximately twice the - time before pause for ``pause_after=N``. + .. note:: + + This function internally uses an exponential delay with jitter between + subsequent responses that contain no new results, up to a maximum delay of just + over a 16 seconds. In practice that means that the time before pause for + ``pause_after=N+1`` is approximately twice the time before pause for + ``pause_after=N``. For example, to create a stream of comment replies, try: @@ -132,8 +129,7 @@ async def stream_generator( async for reply in asyncpraw.models.util.stream_generator(reply_function): print(reply) - To pause a comment stream after six responses with no new - comments, try: + To pause a comment stream after six responses with no new comments, try: .. code-block:: python @@ -160,11 +156,10 @@ async def stream_generator( break print(comment) - To bypass the internal exponential backoff, try the following. This - approach is useful if you are monitoring a subreddit with infrequent - activity, and you want the to consistently learn about new items from the - stream as soon as possible, rather than up to a delay of just over sixteen - seconds. + To bypass the internal exponential backoff, try the following. This approach is + useful if you are monitoring a subreddit with infrequent activity, and you want the + to consistently learn about new items from the stream as soon as possible, rather + than up to a delay of just over sixteen seconds. .. code-block:: python diff --git a/asyncpraw/objector.py b/asyncpraw/objector.py index 73319fc43..9fe4ed12e 100644 --- a/asyncpraw/objector.py +++ b/asyncpraw/objector.py @@ -21,8 +21,9 @@ def parse_error( """Convert JSON response into an error object. :param data: The dict to be converted. - :returns: An instance of :class:`~.RedditAPIException`, or ``None`` if - ``data`` doesn't fit this model. + + :returns: An instance of :class:`~.RedditAPIException`, or ``None`` if ``data`` + doesn't fit this model. """ if isinstance(data, list): @@ -61,6 +62,7 @@ def _objectify_dict(self, data): """Create RedditBase objects from dicts. :param data: The structured data, assumed to be a dict. + :returns: An instance of :class:`~.RedditBase`. """ @@ -147,8 +149,9 @@ def objectify( """Create RedditBase objects from data. :param data: The structured data. - :returns: An instance of :class:`~.RedditBase`, or ``None`` if - given ``data`` is ``None``. + + :returns: An instance of :class:`~.RedditBase`, or ``None`` if given ``data`` is + ``None``. """ # pylint: disable=too-many-return-statements diff --git a/asyncpraw/reddit.py b/asyncpraw/reddit.py index ab3580766..09d507548 100644 --- a/asyncpraw/reddit.py +++ b/asyncpraw/reddit.py @@ -63,16 +63,20 @@ class Reddit: """The Reddit class provides convenient access to Reddit's API. - Instances of this class are the gateway to interacting with Reddit's API - through Async PRAW. The canonical way to obtain an instance of this class is via: - + Instances of this class are the gateway to interacting with Reddit's API through + Async PRAW. The canonical way to obtain an instance of this class is via: .. code-block:: python - import asyncpraw - reddit = asyncpraw.Reddit(client_id="CLIENT_ID", - client_secret="CLIENT_SECRET", password="PASSWORD", - user_agent="USERAGENT", username="USERNAME") + import asyncpraw + + reddit = asyncpraw.Reddit( + client_id="CLIENT_ID", + client_secret="CLIENT_SECRET", + password="PASSWORD", + user_agent="USERAGENT", + username="USERNAME", + ) """ @@ -94,8 +98,8 @@ def read_only(self) -> bool: def read_only(self, value: bool) -> None: """Set or unset the use of the ReadOnlyAuthorizer. - :raises: :class:`ClientException` when attempting to unset ``read_only`` - and only the ReadOnlyAuthorizer is available. + :raises: :class:`ClientException` when attempting to unset ``read_only`` and + only the ReadOnlyAuthorizer is available. """ if value: @@ -113,9 +117,8 @@ def validate_on_submit(self) -> bool: .. deprecated:: 7.0 - If property :attr:`.validate_on_submit` is set to False, the - behavior is deprecated by Reddit. This attribute will be removed - around May-June 2020. + If property :attr:`.validate_on_submit` is set to False, the behavior is + deprecated by Reddit. This attribute will be removed around May-June 2020. """ value = self._validate_on_submit @@ -146,8 +149,8 @@ def __enter__(self): .. deprecated:: 7.1.1 - Using this class as a synchronous context manager is deprecated and will - be removed in the next release. Use this class as an asynchronous context + Using this class as a synchronous context manager is deprecated and will be + removed in the next release. Use this class as an asynchronous context manager instead. """ @@ -179,41 +182,41 @@ def __init__( ): # noqa: D207, D301 """Initialize a Reddit instance. - :param site_name: The name of a section in your ``praw.ini`` file from - which to load settings from. This parameter, in tandem with an - appropriately configured ``praw.ini``, file is useful if you wish - to easily save credentials for different applications, or - communicate with other servers running Reddit. If ``site_name`` is - ``None``, then the site name will be looked for in the environment - variable praw_site. If it is not found there, the DEFAULT site will - be used. - :param requestor_class: A class that will be used to create a - requestor. If not set, use ``asyncprawcore.Requestor`` (default: None). - :param requestor_kwargs: Dictionary with additional keyword arguments - used to initialize the requestor (default: None). + :param site_name: The name of a section in your ``praw.ini`` file from which to + load settings from. This parameter, in tandem with an appropriately + configured ``praw.ini``, file is useful if you wish to easily save + credentials for different applications, or communicate with other servers + running Reddit. If ``site_name`` is ``None``, then the site name will be + looked for in the environment variable praw_site. If it is not found there, + the DEFAULT site will be used. + :param requestor_class: A class that will be used to create a requestor. If not + set, use ``asyncprawcore.Requestor`` (default: None). + :param requestor_kwargs: Dictionary with additional keyword arguments used to + initialize the requestor (default: None). :param token_manager: When provided, the passed instance, a subclass of :class:`.BaseTokenManager`, will manage tokens via two callback functions. This parameter must be provided in order to work with refresh tokens (default: None). - Additional keyword arguments will be used to initialize the - :class:`.Config` object. This can be used to specify configuration - settings during instantiation of the :class:`.Reddit` instance. For - more details, please see :ref:`configuration`. + Additional keyword arguments will be used to initialize the :class:`.Config` + object. This can be used to specify configuration settings during instantiation + of the :class:`.Reddit` instance. For more details, please see + :ref:`configuration`. Required settings are: - * client_id - * client_secret (for installed applications set this value to ``None``) - * user_agent + - client_id + - client_secret (for installed applications set this value to ``None``) + - user_agent - The ``requestor_class`` and ``requestor_kwargs`` allow for - customization of the requestor :class:`.Reddit` will use. This allows, - e.g., easily adding behavior to the requestor or wrapping its - |ClientSession|_ in a caching layer. Example usage: + The ``requestor_class`` and ``requestor_kwargs`` allow for customization of the + requestor :class:`.Reddit` will use. This allows, e.g., easily adding behavior + to the requestor or wrapping its |ClientSession|_ in a caching layer. Example + usage: .. |ClientSession| replace:: ``ClientSession`` - .. _ClientSession: https://docs.aiohttp.org/en/stable/client_advanced.html + + .. _clientsession: https://docs.aiohttp.org/en/stable/client_advanced.html .. code-block:: python @@ -231,9 +234,11 @@ async def request(self, *args, **kwargs): print(json.dumps(await response.json(), indent=4)) return response + my_session = aiohttp.ClientSession(trust_env=True) - reddit = Reddit(..., requestor_class=JSONDebugRequestor, - requestor_kwargs={"session": my_session}) + reddit = Reddit( + ..., requestor_class=JSONDebugRequestor, requestor_kwargs={"session": my_session} + ) You can automatically close the requestor session by using this class as an context manager: @@ -300,8 +305,7 @@ async def request(self, *args, **kwargs): self.auth = models.Auth(self, None) """An instance of :class:`.Auth`. - Provides the interface for interacting with installed and web - applications. + Provides the interface for interacting with installed and web applications. .. seealso:: @@ -312,8 +316,7 @@ async def request(self, *args, **kwargs): self.front = models.Front(self) """An instance of :class:`.Front`. - Provides the interface for interacting with front page listings. For - example: + Provides the interface for interacting with front page listings. For example: .. code-block:: python @@ -325,10 +328,9 @@ async def request(self, *args, **kwargs): self.inbox = models.Inbox(self, None) """An instance of :class:`.Inbox`. - Provides the interface to a user's inbox which produces - :class:`.Message`, :class:`.Comment`, and :class:`.Submission` - instances. For example, to iterate through comments which mention the - authorized user run: + Provides the interface to a user's inbox which produces :class:`.Message`, + :class:`.Comment`, and :class:`.Submission` instances. For example, to iterate + through comments which mention the authorized user run: .. code-block:: python @@ -340,8 +342,8 @@ async def request(self, *args, **kwargs): self.live = models.LiveHelper(self, None) """An instance of :class:`.LiveHelper`. - Provides the interface for working with :class:`.LiveThread` - instances. At present only new LiveThreads can be created. + Provides the interface for working with :class:`.LiveThread` instances. At + present only new LiveThreads can be created. .. code-block:: python @@ -352,9 +354,8 @@ async def request(self, *args, **kwargs): self.multireddit = models.MultiredditHelper(self, None) """An instance of :class:`.MultiredditHelper`. - Provides the interface to working with :class:`.Multireddit` - instances. For example, you can obtain a :class:`.Multireddit` instance - via: + Provides the interface to working with :class:`.Multireddit` instances. For + example, you can obtain a :class:`.Multireddit` instance via: .. code-block:: python @@ -371,8 +372,8 @@ async def request(self, *args, **kwargs): self.redditors = models.Redditors(self, None) """An instance of :class:`.Redditors`. - Provides the interface for Redditor discovery. For example, - to iterate over the newest Redditors, run: + Provides the interface for Redditor discovery. For example, to iterate over the + newest Redditors, run: .. code-block:: python @@ -384,8 +385,8 @@ async def request(self, *args, **kwargs): self.subreddit = models.SubredditHelper(self, None) """An instance of :class:`.SubredditHelper`. - Provides the interface to working with :class:`.Subreddit` - instances. For example, to create a Subreddit run: + Provides the interface to working with :class:`.Subreddit` instances. For + example, to create a Subreddit run: .. code-block:: python @@ -403,8 +404,8 @@ async def request(self, *args, **kwargs): await reddit.subreddit("redditdev", fetch=True) - Multiple subreddits can be combined and filtered views of - r/all can also be used just like a subreddit: + Multiple subreddits can be combined and filtered views of r/all can also be used + just like a subreddit: .. code-block:: python @@ -416,8 +417,8 @@ async def request(self, *args, **kwargs): self.subreddits = models.Subreddits(self, None) """An instance of :class:`.Subreddits`. - Provides the interface for :class:`.Subreddit` discovery. For example, - to iterate over the set of default subreddits run: + Provides the interface for :class:`.Subreddit` discovery. For example, to + iterate over the set of default subreddits run: .. code-block:: python @@ -429,9 +430,8 @@ async def request(self, *args, **kwargs): self.user = models.User(self) """An instance of :class:`.User`. - Provides the interface to the currently authorized - :class:`.Redditor`. For example, to get the name of the current user - run: + Provides the interface to the currently authorized :class:`.Redditor`. For + example, to get the name of the current user run: .. code-block:: python @@ -567,17 +567,19 @@ async def comment( :param url: A permalink pointing to the comment. :param lazy: If True, object is loaded lazily (default: False). - If you don't need the object fetched right away (e.g., to utilize a - class method) then you can do: + If you don't need the object fetched right away (e.g., to utilize a class + method) then you can do: .. code-block:: python comment = await reddit.comment("comment_id", lazy=True) await comment.reply("reply") - .. note:: If call this with ``lazy=True`` and you need to obtain the - comment's replies, you will need to call this without ``lazy=True`` - or call :meth:`~.Comment.refresh` on the returned :class:`.Comment`. + .. note:: + + If call this with ``lazy=True`` and you need to obtain the comment's + replies, you will need to call this without ``lazy=True`` or call + :meth:`~.Comment.refresh` on the returned :class:`.Comment`. """ comment = models.Comment(self, id=id, url=url) @@ -601,8 +603,7 @@ async def get( """Return parsed objects returned from a GET request to ``path``. :param path: The path to fetch. - :param params: The query parameters to add to the request (default: - None). + :param params: The query parameters to add to the request (default: None). """ return await self._objectify_request(method="GET", params=params, path=path) @@ -624,23 +625,26 @@ def info( :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 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 - issued in batches for each 100 fullnames. + Items that cannot be matched will not be generated. Requests will be issued in + batches for each 100 fullnames. + + .. note:: - .. note:: For comments that are retrieved via this method, if you want - to obtain its replies, you will need to call - :meth:`~.Comment.refresh` on the yielded :class:`.Comment`. + For comments that are retrieved via this method, if you want to obtain its + replies, you will need to call :meth:`~.Comment.refresh` on the yielded + :class:`.Comment`. - .. note:: When using the URL option, it is important to be aware that - URLs are treated literally by Reddit's API. As such, the URLs - "youtube.com" and "https://www.youtube.com" will provide a - different set of submissions. + .. note:: + + When using the URL option, it is important to be aware that URLs are treated + literally by Reddit's API. As such, the URLs "youtube.com" and + "https://www.youtube.com" will provide a different set of submissions. """ none_count = (fullnames, url, subreddits).count(None) @@ -693,16 +697,15 @@ async def _objectify_request( ) -> Any: """Run a request through the ``Objector``. - :param data: Dictionary, bytes, or file-like object to send in the body - of the request (default: None). - :param files: Dictionary, filename to file (like) object mapping - (default: None). - :param json: JSON-serializable object to send in the body - of the request with a Content-Type header of application/json - (default: None). If ``json`` is provided, ``data`` should not be. - :param method: The HTTP method (e.g., GET, POST, PUT, DELETE). - :param params: The query parameters to add to the request (default: + :param data: Dictionary, bytes, or file-like object to send in the body of the + request (default: None). + :param files: Dictionary, filename to file (like) object mapping (default: None). + :param json: JSON-serializable object to send in the body of the request with a + Content-Type header of application/json (default: None). If ``json`` is + provided, ``data`` should not be. + :param method: The HTTP method (e.g., GET, POST, PUT, DELETE). + :param params: The query parameters to add to the request (default: None). :param path: The path to fetch. """ @@ -742,11 +745,11 @@ async def delete( """Return parsed objects returned from a DELETE request to ``path``. :param path: The path to fetch. - :param data: Dictionary, bytes, or file-like object to send in the body - of the request (default: None). - :param json: JSON-serializable object to send in the body - of the request with a Content-Type header of application/json - (default: None). If ``json`` is provided, ``data`` should not be. + :param data: Dictionary, bytes, or file-like object to send in the body of the + request (default: None). + :param json: JSON-serializable object to send in the body of the request with a + Content-Type header of application/json (default: None). If ``json`` is + provided, ``data`` should not be. """ return await self._objectify_request( @@ -762,11 +765,11 @@ async def patch( """Return parsed objects returned from a PATCH request to ``path``. :param path: The path to fetch. - :param data: Dictionary, bytes, or file-like object to send in the body - of the request (default: None). - :param json: JSON-serializable object to send in the body - of the request with a Content-Type header of application/json - (default: None). If ``json`` is provided, ``data`` should not be. + :param data: Dictionary, bytes, or file-like object to send in the body of the + request (default: None). + :param json: JSON-serializable object to send in the body of the request with a + Content-Type header of application/json (default: None). If ``json`` is + provided, ``data`` should not be. """ return await self._objectify_request( @@ -784,15 +787,14 @@ async def post( """Return parsed objects returned from a POST request to ``path``. :param path: The path to fetch. - :param data: Dictionary, bytes, or file-like object to send in the body - of the request (default: None). - :param files: Dictionary, filename to file (like) object mapping - (default: None). - :param params: The query parameters to add to the request (default: + :param data: Dictionary, bytes, or file-like object to send in the body of the + request (default: None). + :param files: Dictionary, filename to file (like) object mapping (default: None). - :param json: JSON-serializable object to send in the body - of the request with a Content-Type header of application/json - (default: None). If ``json`` is provided, ``data`` should not be. + :param params: The query parameters to add to the request (default: None). + :param json: JSON-serializable object to send in the body of the request with a + Content-Type header of application/json (default: None). If ``json`` is + provided, ``data`` should not be. """ if json is None: @@ -829,11 +831,11 @@ async def put( """Return parsed objects returned from a PUT request to ``path``. :param path: The path to fetch. - :param data: Dictionary, bytes, or file-like object to send in the body - of the request (default: None). - :param json: JSON-serializable object to send in the body - of the request with a Content-Type header of application/json - (default: None). If ``json`` is provided, ``data`` should not be. + :param data: Dictionary, bytes, or file-like object to send in the body of the + request (default: None). + :param json: JSON-serializable object to send in the body of the request with a + Content-Type header of application/json (default: None). If ``json`` is + provided, ``data`` should not be. """ return await self._objectify_request( @@ -845,8 +847,8 @@ async def random_subreddit( ) -> "asyncpraw.models.Subreddit": """Return a random instance of :class:`~.Subreddit`. - :param nsfw: Return a random NSFW (not safe for work) subreddit - (default: False). + :param nsfw: Return a random NSFW (not safe for work) subreddit (default: + False). """ url = API_PATH["subreddit"].format(subreddit="randnsfw" if nsfw else "random") @@ -891,15 +893,14 @@ async def request( :param method: The HTTP method (e.g., GET, POST, PUT, DELETE). :param path: The path to fetch. - :param params: The query parameters to add to the request (default: + :param params: The query parameters to add to the request (default: None). + :param data: Dictionary, bytes, or file-like object to send in the body of the + request (default: None). + :param files: Dictionary, filename to file (like) object mapping (default: None). - :param data: Dictionary, bytes, or file-like object to send in the body - of the request (default: None). - :param files: Dictionary, filename to file (like) object mapping - (default: None). - :param json: JSON-serializable object to send in the body - of the request with a Content-Type header of application/json - (default: None). If ``json`` is provided, ``data`` should not be. + :param json: JSON-serializable object to send in the body of the request with a + Content-Type header of application/json (default: None). If ``json`` is + provided, ``data`` should not be. """ if data and json: @@ -941,13 +942,14 @@ async def submission( # pylint: disable=invalid-name,redefined-builtin """Return an instance of :class:`~.Submission`. :param id: A Reddit base36 submission ID, e.g., ``2gmzqe``. - :param url: A URL supported by :meth:`~asyncpraw.models.Submission.id_from_url`.`. + :param url: A URL supported by + :meth:`~asyncpraw.models.Submission.id_from_url`.`. :param lazy: If True, object is loaded lazily (default: False). Either ``id`` or ``url`` can be provided, but not both. - If you don't need the object fetched right away (e.g., to utilize a - class method) then you can do: + If you don't need the object fetched right away (e.g., to utilize a class + method) then you can do: .. code-block:: python diff --git a/asyncpraw/util/cache.py b/asyncpraw/util/cache.py index d395a3d0d..016f7082e 100644 --- a/asyncpraw/util/cache.py +++ b/asyncpraw/util/cache.py @@ -5,18 +5,18 @@ class cachedproperty: """A decorator for caching a property's result. - Similar to `property`, but the wrapped method's result is cached - on the instance. This is achieved by setting an entry in the object's - instance dictionary with the same name as the property. When the name - is later accessed, the value in the instance dictionary takes precedence - over the (non-data descriptor) property. + Similar to `property`, but the wrapped method's result is cached on the instance. + This is achieved by setting an entry in the object's instance dictionary with the + same name as the property. When the name is later accessed, the value in the + instance dictionary takes precedence over the (non-data descriptor) property. This is useful for implementing lazy-loaded properties. - The cache can be invalidated via `delattr()`, or by modifying `__dict__` - directly. It will be repopulated on next access. + The cache can be invalidated via `delattr()`, or by modifying `__dict__` directly. + It will be repopulated on next access. .. versionadded:: 6.3.0 + """ def __init__(self, func: Callable[[Any], Any], doc: Optional[str] = None): @@ -34,8 +34,9 @@ def __call__(self, *args, **kwargs): # pragma: no cover noqa: D102 def __get__(self, obj: Optional[Any], objtype: Optional[Any] = None) -> Any: """Implement descriptor getter. - Calculate the property's value and then store it in the - associated object's instance dictionary. + Calculate the property's value and then store it in the associated object's + instance dictionary. + """ if obj is None: return self diff --git a/asyncpraw/util/token_manager.py b/asyncpraw/util/token_manager.py index 72ee61fad..46ad3328f 100644 --- a/asyncpraw/util/token_manager.py +++ b/asyncpraw/util/token_manager.py @@ -38,9 +38,8 @@ def post_refresh_callback(self, authorizer): :param authorizer: The ``asyncprawcore.Authorizer`` instance used containing ``access_token`` and ``refresh_token`` attributes. - This function will be called after refreshing the access and refresh - tokens. This callback can be used for saving the updated - ``refresh_token``. + This function will be called after refreshing the access and refresh tokens. + This callback can be used for saving the updated ``refresh_token``. """ raise NotImplementedError("``post_refresh_callback`` must be extended.") @@ -52,8 +51,7 @@ def pre_refresh_callback(self, authorizer): ``access_token`` and ``refresh_token`` attributes. This callback can be used to inspect and modify the attributes of the - ``asyncprawcore.Authorizer`` instance, such as setting the - ``refresh_token``. + ``asyncprawcore.Authorizer`` instance, such as setting the ``refresh_token``. """ raise NotImplementedError("``pre_refresh_callback`` must be extended.") diff --git a/docs/code_overview/asyncpraw_models.rst b/docs/code_overview/asyncpraw_models.rst index 9ff532448..a9b87cc75 100644 --- a/docs/code_overview/asyncpraw_models.rst +++ b/docs/code_overview/asyncpraw_models.rst @@ -2,17 +2,17 @@ Working with Async PRAW's Models ================================ .. toctree:: - :maxdepth: 2 - :caption: Models + :maxdepth: 2 + :caption: Models - models/comment - models/livethread - models/liveupdate - models/message - models/modmailconversation - models/more - models/multireddit - models/redditor - models/submission - models/subreddit - models/wikipage + models/comment + models/livethread + models/liveupdate + models/message + models/modmailconversation + models/more + models/multireddit + models/redditor + models/submission + models/subreddit + models/wikipage diff --git a/docs/code_overview/exceptions.rst b/docs/code_overview/exceptions.rst index 2f5c13cf7..7de70394c 100644 --- a/docs/code_overview/exceptions.rst +++ b/docs/code_overview/exceptions.rst @@ -2,13 +2,12 @@ Exceptions in Async PRAW ======================== In addition to exceptions under the ``asyncpraw.exceptions`` namespace shown below, -exceptions might be raised that inherit from -``asyncprawcore.AsyncPrawcoreException``. Please see the following resource for -information on those exceptions: +exceptions might be raised that inherit from ``asyncprawcore.AsyncPrawcoreException``. +Please see the following resource for information on those exceptions: https://github.com/praw-dev/asyncprawcore/blob/master/asyncprawcore/exceptions.py asyncpraw.exceptions -------------------- .. automodule:: asyncpraw.exceptions - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/models/comment.rst b/docs/code_overview/models/comment.rst index 149aee449..5ef5c742a 100644 --- a/docs/code_overview/models/comment.rst +++ b/docs/code_overview/models/comment.rst @@ -2,6 +2,6 @@ Comment ======= .. autoclass:: asyncpraw.models.Comment - :inherited-members: + :inherited-members: .. include:: note_dynamically_provided_attributes.txt diff --git a/docs/code_overview/models/livethread.rst b/docs/code_overview/models/livethread.rst index b89637edb..b01fee924 100644 --- a/docs/code_overview/models/livethread.rst +++ b/docs/code_overview/models/livethread.rst @@ -2,6 +2,6 @@ LiveThread ========== .. autoclass:: asyncpraw.models.LiveThread - :inherited-members: + :inherited-members: .. include:: note_dynamically_provided_attributes.txt diff --git a/docs/code_overview/models/liveupdate.rst b/docs/code_overview/models/liveupdate.rst index f710ce512..eb03eb994 100644 --- a/docs/code_overview/models/liveupdate.rst +++ b/docs/code_overview/models/liveupdate.rst @@ -2,6 +2,6 @@ LiveUpdate ========== .. autoclass:: asyncpraw.models.LiveUpdate - :inherited-members: + :inherited-members: .. include:: note_dynamically_provided_attributes.txt diff --git a/docs/code_overview/models/message.rst b/docs/code_overview/models/message.rst index c44de65a2..a7cb2b001 100644 --- a/docs/code_overview/models/message.rst +++ b/docs/code_overview/models/message.rst @@ -2,6 +2,6 @@ Message ======= .. autoclass:: asyncpraw.models.Message - :inherited-members: + :inherited-members: .. include:: note_dynamically_provided_attributes.txt diff --git a/docs/code_overview/models/modmailconversation.rst b/docs/code_overview/models/modmailconversation.rst index 16a28c529..1b0a55abb 100644 --- a/docs/code_overview/models/modmailconversation.rst +++ b/docs/code_overview/models/modmailconversation.rst @@ -2,6 +2,6 @@ ModmailConversation =================== .. autoclass:: asyncpraw.models.reddit.modmail.ModmailConversation - :inherited-members: + :inherited-members: .. include:: note_dynamically_provided_attributes.txt diff --git a/docs/code_overview/models/more.rst b/docs/code_overview/models/more.rst index 6c78857d2..72a075974 100644 --- a/docs/code_overview/models/more.rst +++ b/docs/code_overview/models/more.rst @@ -2,6 +2,6 @@ MoreComments ============ .. autoclass:: asyncpraw.models.MoreComments - :inherited-members: + :inherited-members: .. include:: note_dynamically_provided_attributes.txt diff --git a/docs/code_overview/models/multireddit.rst b/docs/code_overview/models/multireddit.rst index a0db0100e..6900a9173 100644 --- a/docs/code_overview/models/multireddit.rst +++ b/docs/code_overview/models/multireddit.rst @@ -2,6 +2,6 @@ Multireddit =========== .. autoclass:: asyncpraw.models.Multireddit - :inherited-members: + :inherited-members: .. include:: note_dynamically_provided_attributes.txt diff --git a/docs/code_overview/models/redditor.rst b/docs/code_overview/models/redditor.rst index fa7e113f9..cf0ac6cfa 100644 --- a/docs/code_overview/models/redditor.rst +++ b/docs/code_overview/models/redditor.rst @@ -2,6 +2,6 @@ Redditor ======== .. autoclass:: asyncpraw.models.Redditor - :inherited-members: + :inherited-members: .. include:: note_dynamically_provided_attributes.txt diff --git a/docs/code_overview/models/submission.rst b/docs/code_overview/models/submission.rst index e2a1170e3..f03404acf 100644 --- a/docs/code_overview/models/submission.rst +++ b/docs/code_overview/models/submission.rst @@ -2,6 +2,6 @@ Submission ========== .. autoclass:: asyncpraw.models.Submission - :inherited-members: + :inherited-members: .. include:: note_dynamically_provided_attributes.txt diff --git a/docs/code_overview/models/subreddit.rst b/docs/code_overview/models/subreddit.rst index da250b0e9..2ae775f7b 100644 --- a/docs/code_overview/models/subreddit.rst +++ b/docs/code_overview/models/subreddit.rst @@ -2,6 +2,6 @@ Subreddit ========= .. autoclass:: asyncpraw.models.Subreddit - :inherited-members: + :inherited-members: .. include:: note_dynamically_provided_attributes.txt diff --git a/docs/code_overview/models/wikipage.rst b/docs/code_overview/models/wikipage.rst index 57b492508..6ea973531 100644 --- a/docs/code_overview/models/wikipage.rst +++ b/docs/code_overview/models/wikipage.rst @@ -2,6 +2,6 @@ WikiPage ======== .. autoclass:: asyncpraw.models.reddit.wikipage.WikiPage - :inherited-members: + :inherited-members: .. include:: note_dynamically_provided_attributes.txt diff --git a/docs/code_overview/other.rst b/docs/code_overview/other.rst index efd8d3c2a..371a892a6 100644 --- a/docs/code_overview/other.rst +++ b/docs/code_overview/other.rst @@ -1,127 +1,127 @@ Other Classes ============= -The following list of classes are provided here for complete documentation. You -should not likely need to work with these classes directly, but rather through -instances of them bound to an attribute of one of the Async PRAW models. +The following list of classes are provided here for complete documentation. You should +not likely need to work with these classes directly, but rather through instances of +them bound to an attribute of one of the Async PRAW models. .. toctree:: - :maxdepth: 2 - :caption: Collections + :maxdepth: 2 + :caption: Collections - other/collection - other/collectionmoderation - other/subredditcollections - other/subredditcollectionsmoderation + other/collection + other/collectionmoderation + other/subredditcollections + other/subredditcollectionsmoderation .. toctree:: - :maxdepth: 2 - :caption: Flair Helpers + :maxdepth: 2 + :caption: Flair Helpers - other/submissionflair - other/subredditflair - other/subredditflairtemplates - other/subredditlinkflairtemplates - other/subredditredditorflairtemplates + other/submissionflair + other/subredditflair + other/subredditflairtemplates + other/subredditlinkflairtemplates + other/subredditredditorflairtemplates .. toctree:: - :maxdepth: 2 - :caption: Reddit Live Helpers + :maxdepth: 2 + :caption: Reddit Live Helpers - other/livecontributorrelationship - other/livethreadcontribution - other/livethreadstream - other/liveupdatecontribution + other/livecontributorrelationship + other/livethreadcontribution + other/livethreadstream + other/liveupdatecontribution .. toctree:: - :maxdepth: 2 - :caption: Moderation Helpers - - other/commentmoderation - other/submissionmoderation - other/rulemoderation - other/subredditmoderation - other/subredditrulesmoderation - other/subredditwidgetsmoderation - other/thingmoderationmixin - other/widgetmoderation - other/wikipagemoderation + :maxdepth: 2 + :caption: Moderation Helpers + + other/commentmoderation + other/submissionmoderation + other/rulemoderation + other/subredditmoderation + other/subredditrulesmoderation + other/subredditwidgetsmoderation + other/thingmoderationmixin + other/widgetmoderation + other/wikipagemoderation .. toctree:: - :maxdepth: 2 - :caption: Relationship Helpers + :maxdepth: 2 + :caption: Relationship Helpers - other/contributorrelationship - other/moderatorrelationship - other/subredditrelationship + other/contributorrelationship + other/moderatorrelationship + other/subredditrelationship .. toctree:: - :maxdepth: 2 - :caption: Subreddit Helpers + :maxdepth: 2 + :caption: Subreddit Helpers - other/subredditfilters - other/subredditquarantine - other/subredditstream - other/subredditmoderationstream - other/subredditstylesheet - other/subredditwidgets - other/subredditwiki + other/subredditfilters + other/subredditquarantine + other/subredditstream + other/subredditmoderationstream + other/subredditstylesheet + other/subredditwidgets + other/subredditwiki .. toctree:: - :maxdepth: 2 - :caption: Widgets - - other/buttonwidget - other/calendar - other/communitylist - other/customwidget - other/idcard - other/imagewidget - other/menu - other/moderatorswidget - other/postflairwidget - other/ruleswidget - other/textarea + :maxdepth: 2 + :caption: Widgets + + other/buttonwidget + other/calendar + other/communitylist + other/customwidget + other/idcard + other/imagewidget + other/menu + other/moderatorswidget + other/postflairwidget + other/ruleswidget + other/textarea .. toctree:: - :maxdepth: 2 - :caption: Others - - other/auth - other/button - other/calendarconfiguration - other/commentforest - other/commenthelper - other/config - other/domainlisting - other/emoji - other/hover - other/listinggenerator - other/image - other/imagedata - other/inlinemedia - other/inlinegif - other/inlineimage - other/inlinevideo - other/menulink - other/mod_action - other/modmail - other/modmailmessage - other/preferences - other/poll - other/redditbase - other/redditorlist - other/removalreason - other/rule - other/styles - other/stylesheet - other/sublisting - other/submenu - other/subredditemoji - other/subredditmessage - other/subredditremovalreasons - other/subredditrules - other/redditorstream - other/token_manager - other/trophy - other/util + :maxdepth: 2 + :caption: Others + + other/auth + other/button + other/calendarconfiguration + other/commentforest + other/commenthelper + other/config + other/domainlisting + other/emoji + other/hover + other/listinggenerator + other/image + other/imagedata + other/inlinemedia + other/inlinegif + other/inlineimage + other/inlinevideo + other/menulink + other/mod_action + other/modmail + other/modmailmessage + other/preferences + other/poll + other/redditbase + other/redditorlist + other/removalreason + other/rule + other/styles + other/stylesheet + other/sublisting + other/submenu + other/subredditemoji + other/subredditmessage + other/subredditremovalreasons + other/subredditrules + other/redditorstream + other/token_manager + other/trophy + other/util diff --git a/docs/code_overview/other/auth.rst b/docs/code_overview/other/auth.rst index 1d61211fb..8c2fde702 100644 --- a/docs/code_overview/other/auth.rst +++ b/docs/code_overview/other/auth.rst @@ -2,4 +2,4 @@ Auth ==== .. autoclass:: asyncpraw.models.Auth - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/button.rst b/docs/code_overview/other/button.rst index 9a452bb6b..3861ef0a2 100755 --- a/docs/code_overview/other/button.rst +++ b/docs/code_overview/other/button.rst @@ -1,4 +1,5 @@ Button ====== + .. autoclass:: asyncpraw.models.Button - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/buttonwidget.rst b/docs/code_overview/other/buttonwidget.rst index c0f149cc5..7d66d4298 100755 --- a/docs/code_overview/other/buttonwidget.rst +++ b/docs/code_overview/other/buttonwidget.rst @@ -1,6 +1,7 @@ ButtonWidget ============ + .. autoclass:: asyncpraw.models.ButtonWidget - :inherited-members: + :inherited-members: .. include:: ../models/note_dynamically_provided_attributes.txt diff --git a/docs/code_overview/other/calendar.rst b/docs/code_overview/other/calendar.rst index 72c66d33e..80cdeb6e8 100755 --- a/docs/code_overview/other/calendar.rst +++ b/docs/code_overview/other/calendar.rst @@ -1,6 +1,7 @@ Calendar ======== + .. autoclass:: asyncpraw.models.Calendar - :inherited-members: + :inherited-members: .. include:: ../models/note_dynamically_provided_attributes.txt diff --git a/docs/code_overview/other/calendarconfiguration.rst b/docs/code_overview/other/calendarconfiguration.rst index 91d487d62..997492532 100644 --- a/docs/code_overview/other/calendarconfiguration.rst +++ b/docs/code_overview/other/calendarconfiguration.rst @@ -1,4 +1,5 @@ CalendarConfiguration ===================== + .. autoclass:: asyncpraw.models.CalendarConfiguration - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/collection.rst b/docs/code_overview/other/collection.rst index 7e5188092..3a7a67fb1 100644 --- a/docs/code_overview/other/collection.rst +++ b/docs/code_overview/other/collection.rst @@ -1,6 +1,7 @@ Collection ========== + .. autoclass:: asyncpraw.models.Collection - :inherited-members: + :inherited-members: .. include:: ../models/note_dynamically_provided_attributes.txt diff --git a/docs/code_overview/other/collectionmoderation.rst b/docs/code_overview/other/collectionmoderation.rst index b84719609..00cafc9d7 100644 --- a/docs/code_overview/other/collectionmoderation.rst +++ b/docs/code_overview/other/collectionmoderation.rst @@ -1,4 +1,5 @@ CollectionModeration ==================== + .. autoclass:: asyncpraw.models.reddit.collections.CollectionModeration - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/commentforest.rst b/docs/code_overview/other/commentforest.rst index 901cf1cfd..8f01ace13 100644 --- a/docs/code_overview/other/commentforest.rst +++ b/docs/code_overview/other/commentforest.rst @@ -2,4 +2,4 @@ CommentForest ============= .. autoclass:: asyncpraw.models.comment_forest.CommentForest - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/commenthelper.rst b/docs/code_overview/other/commenthelper.rst index fc3a91238..add30c156 100644 --- a/docs/code_overview/other/commenthelper.rst +++ b/docs/code_overview/other/commenthelper.rst @@ -2,4 +2,4 @@ CommentHelper ============= .. autoclass:: asyncpraw.models.listing.mixins.subreddit.CommentHelper - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/commentmoderation.rst b/docs/code_overview/other/commentmoderation.rst index f090e965e..a7c2e9b40 100644 --- a/docs/code_overview/other/commentmoderation.rst +++ b/docs/code_overview/other/commentmoderation.rst @@ -2,4 +2,4 @@ CommentModeration ================= .. autoclass:: asyncpraw.models.reddit.comment.CommentModeration - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/communitylist.rst b/docs/code_overview/other/communitylist.rst index 3864868c3..ee6b6e21d 100755 --- a/docs/code_overview/other/communitylist.rst +++ b/docs/code_overview/other/communitylist.rst @@ -1,6 +1,7 @@ CommunityList ============= + .. autoclass:: asyncpraw.models.CommunityList - :inherited-members: + :inherited-members: .. include:: ../models/note_dynamically_provided_attributes.txt diff --git a/docs/code_overview/other/config.rst b/docs/code_overview/other/config.rst index 06a7b6b1a..63eed84b3 100644 --- a/docs/code_overview/other/config.rst +++ b/docs/code_overview/other/config.rst @@ -2,4 +2,4 @@ Config ====== .. autoclass:: asyncpraw.config.Config - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/contributorrelationship.rst b/docs/code_overview/other/contributorrelationship.rst index aa030a57e..48bb0829a 100644 --- a/docs/code_overview/other/contributorrelationship.rst +++ b/docs/code_overview/other/contributorrelationship.rst @@ -2,4 +2,4 @@ ContributorRelationship ======================= .. autoclass:: asyncpraw.models.reddit.subreddit.ContributorRelationship - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/customwidget.rst b/docs/code_overview/other/customwidget.rst index 014f41379..a72bc83a4 100755 --- a/docs/code_overview/other/customwidget.rst +++ b/docs/code_overview/other/customwidget.rst @@ -1,6 +1,7 @@ CustomWidget ============ + .. autoclass:: asyncpraw.models.CustomWidget - :inherited-members: + :inherited-members: .. include:: ../models/note_dynamically_provided_attributes.txt diff --git a/docs/code_overview/other/domainlisting.rst b/docs/code_overview/other/domainlisting.rst index fcfa2f8ad..fac513b5c 100644 --- a/docs/code_overview/other/domainlisting.rst +++ b/docs/code_overview/other/domainlisting.rst @@ -2,4 +2,4 @@ DomainListing ============= .. autoclass:: asyncpraw.models.DomainListing - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/emoji.rst b/docs/code_overview/other/emoji.rst index 9a853a35d..b501d424b 100644 --- a/docs/code_overview/other/emoji.rst +++ b/docs/code_overview/other/emoji.rst @@ -2,4 +2,4 @@ Emoji ===== .. autoclass:: asyncpraw.models.reddit.emoji.Emoji - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/hover.rst b/docs/code_overview/other/hover.rst index 84abd5a30..ef24a8db0 100644 --- a/docs/code_overview/other/hover.rst +++ b/docs/code_overview/other/hover.rst @@ -1,4 +1,5 @@ Hover ===== + .. autoclass:: asyncpraw.models.Hover - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/idcard.rst b/docs/code_overview/other/idcard.rst index 1a594ee8d..9ea942147 100755 --- a/docs/code_overview/other/idcard.rst +++ b/docs/code_overview/other/idcard.rst @@ -1,6 +1,7 @@ IDCard ====== + .. autoclass:: asyncpraw.models.IDCard - :inherited-members: + :inherited-members: .. include:: ../models/note_dynamically_provided_attributes.txt diff --git a/docs/code_overview/other/image.rst b/docs/code_overview/other/image.rst index e5df97d58..f30b887bf 100755 --- a/docs/code_overview/other/image.rst +++ b/docs/code_overview/other/image.rst @@ -2,4 +2,4 @@ Image ===== .. autoclass:: asyncpraw.models.Image - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/imagedata.rst b/docs/code_overview/other/imagedata.rst index 5ae7675a0..8a1310426 100755 --- a/docs/code_overview/other/imagedata.rst +++ b/docs/code_overview/other/imagedata.rst @@ -2,4 +2,4 @@ ImageData ========= .. autoclass:: asyncpraw.models.ImageData - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/imagewidget.rst b/docs/code_overview/other/imagewidget.rst index 0bd5b423b..fcd91edc7 100755 --- a/docs/code_overview/other/imagewidget.rst +++ b/docs/code_overview/other/imagewidget.rst @@ -1,6 +1,7 @@ ImageWidget =========== + .. autoclass:: asyncpraw.models.ImageWidget - :inherited-members: + :inherited-members: .. include:: ../models/note_dynamically_provided_attributes.txt diff --git a/docs/code_overview/other/inlinegif.rst b/docs/code_overview/other/inlinegif.rst index e0aa2cd51..838940c57 100644 --- a/docs/code_overview/other/inlinegif.rst +++ b/docs/code_overview/other/inlinegif.rst @@ -2,4 +2,4 @@ InlineGif ========= .. autoclass:: asyncpraw.models.InlineGif - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/inlineimage.rst b/docs/code_overview/other/inlineimage.rst index 2acb0d73d..85f9d3ca9 100644 --- a/docs/code_overview/other/inlineimage.rst +++ b/docs/code_overview/other/inlineimage.rst @@ -2,4 +2,4 @@ InlineImage =========== .. autoclass:: asyncpraw.models.InlineImage - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/inlinemedia.rst b/docs/code_overview/other/inlinemedia.rst index 6508558cb..00dfc3c57 100644 --- a/docs/code_overview/other/inlinemedia.rst +++ b/docs/code_overview/other/inlinemedia.rst @@ -2,4 +2,4 @@ InlineMedia =========== .. autoclass:: asyncpraw.models.InlineMedia - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/inlinevideo.rst b/docs/code_overview/other/inlinevideo.rst index f73df6973..eeffcd5f7 100644 --- a/docs/code_overview/other/inlinevideo.rst +++ b/docs/code_overview/other/inlinevideo.rst @@ -2,4 +2,4 @@ InlineVideo =========== .. autoclass:: asyncpraw.models.InlineVideo - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/listinggenerator.rst b/docs/code_overview/other/listinggenerator.rst index 137151677..462aa81d6 100644 --- a/docs/code_overview/other/listinggenerator.rst +++ b/docs/code_overview/other/listinggenerator.rst @@ -2,4 +2,4 @@ ListingGenerator ================ .. autoclass:: asyncpraw.models.ListingGenerator - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/livecontributorrelationship.rst b/docs/code_overview/other/livecontributorrelationship.rst index 0e18f3c55..cdfef1c67 100644 --- a/docs/code_overview/other/livecontributorrelationship.rst +++ b/docs/code_overview/other/livecontributorrelationship.rst @@ -2,4 +2,4 @@ LiveContributorRelationship =========================== .. autoclass:: asyncpraw.models.reddit.live.LiveContributorRelationship - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/livethreadcontribution.rst b/docs/code_overview/other/livethreadcontribution.rst index 66267c2d2..6084b962e 100644 --- a/docs/code_overview/other/livethreadcontribution.rst +++ b/docs/code_overview/other/livethreadcontribution.rst @@ -2,4 +2,4 @@ LiveThreadContribution ====================== .. autoclass:: asyncpraw.models.reddit.live.LiveThreadContribution - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/livethreadstream.rst b/docs/code_overview/other/livethreadstream.rst index 2854fe8af..7d8a4a1aa 100644 --- a/docs/code_overview/other/livethreadstream.rst +++ b/docs/code_overview/other/livethreadstream.rst @@ -2,4 +2,4 @@ LiveThreadStream ================ .. autoclass:: asyncpraw.models.reddit.live.LiveThreadStream - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/liveupdatecontribution.rst b/docs/code_overview/other/liveupdatecontribution.rst index c937ca4dd..95785a90a 100644 --- a/docs/code_overview/other/liveupdatecontribution.rst +++ b/docs/code_overview/other/liveupdatecontribution.rst @@ -2,4 +2,4 @@ LiveUpdateContribution ====================== .. autoclass:: asyncpraw.models.reddit.live.LiveUpdateContribution - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/menu.rst b/docs/code_overview/other/menu.rst index e023c209b..cc7bd9bfe 100755 --- a/docs/code_overview/other/menu.rst +++ b/docs/code_overview/other/menu.rst @@ -2,6 +2,6 @@ Menu ==== .. autoclass:: asyncpraw.models.Menu - :inherited-members: + :inherited-members: .. include:: ../models/note_dynamically_provided_attributes.txt diff --git a/docs/code_overview/other/menulink.rst b/docs/code_overview/other/menulink.rst index c72013595..0af258481 100755 --- a/docs/code_overview/other/menulink.rst +++ b/docs/code_overview/other/menulink.rst @@ -2,4 +2,4 @@ MenuLink ======== .. autoclass:: asyncpraw.models.MenuLink - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/mod_action.rst b/docs/code_overview/other/mod_action.rst index e3609b69f..db51aa153 100755 --- a/docs/code_overview/other/mod_action.rst +++ b/docs/code_overview/other/mod_action.rst @@ -2,4 +2,4 @@ ModAction ========= .. autoclass:: asyncpraw.models.ModAction - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/moderatorrelationship.rst b/docs/code_overview/other/moderatorrelationship.rst index f5d2569cc..78d3c945e 100644 --- a/docs/code_overview/other/moderatorrelationship.rst +++ b/docs/code_overview/other/moderatorrelationship.rst @@ -2,4 +2,4 @@ ModeratorRelationship ===================== .. autoclass:: asyncpraw.models.reddit.subreddit.ModeratorRelationship - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/moderatorswidget.rst b/docs/code_overview/other/moderatorswidget.rst index 499cb09fb..26340abf9 100755 --- a/docs/code_overview/other/moderatorswidget.rst +++ b/docs/code_overview/other/moderatorswidget.rst @@ -1,6 +1,7 @@ ModeratorsWidget ================ + .. autoclass:: asyncpraw.models.ModeratorsWidget - :inherited-members: + :inherited-members: .. include:: ../models/note_dynamically_provided_attributes.txt diff --git a/docs/code_overview/other/modmail.rst b/docs/code_overview/other/modmail.rst index 041966d81..4e55b0f93 100644 --- a/docs/code_overview/other/modmail.rst +++ b/docs/code_overview/other/modmail.rst @@ -2,4 +2,4 @@ Modmail ======= .. autoclass:: asyncpraw.models.reddit.subreddit.Modmail - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/modmailmessage.rst b/docs/code_overview/other/modmailmessage.rst index 6c7fa03be..232b6e32f 100644 --- a/docs/code_overview/other/modmailmessage.rst +++ b/docs/code_overview/other/modmailmessage.rst @@ -2,4 +2,4 @@ ModmailMessage ============== .. autoclass:: asyncpraw.models.ModmailMessage - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/poll.rst b/docs/code_overview/other/poll.rst index c743c729b..bc9c0820b 100644 --- a/docs/code_overview/other/poll.rst +++ b/docs/code_overview/other/poll.rst @@ -2,9 +2,9 @@ Polls ===== .. autoclass:: asyncpraw.models.reddit.poll.PollData - :inherited-members: + :inherited-members: .. autoclass:: asyncpraw.models.reddit.poll.PollOption - :inherited-members: + :inherited-members: .. include:: ../models/note_dynamically_provided_attributes.txt diff --git a/docs/code_overview/other/postflairwidget.rst b/docs/code_overview/other/postflairwidget.rst index 91010fe1b..865971040 100755 --- a/docs/code_overview/other/postflairwidget.rst +++ b/docs/code_overview/other/postflairwidget.rst @@ -2,4 +2,4 @@ PostFlairWidget =============== .. autoclass:: asyncpraw.models.PostFlairWidget - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/preferences.rst b/docs/code_overview/other/preferences.rst index bade44a6f..2334d1c0e 100644 --- a/docs/code_overview/other/preferences.rst +++ b/docs/code_overview/other/preferences.rst @@ -2,4 +2,4 @@ Preferences =========== .. autoclass:: asyncpraw.models.Preferences - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/redditbase.rst b/docs/code_overview/other/redditbase.rst index 5e63f7cf2..6db019ec9 100644 --- a/docs/code_overview/other/redditbase.rst +++ b/docs/code_overview/other/redditbase.rst @@ -2,4 +2,4 @@ RedditBase ========== .. autoclass:: asyncpraw.models.reddit.base.RedditBase - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/redditorlist.rst b/docs/code_overview/other/redditorlist.rst index 67826dc49..05967b6df 100644 --- a/docs/code_overview/other/redditorlist.rst +++ b/docs/code_overview/other/redditorlist.rst @@ -2,4 +2,4 @@ RedditorList ============ .. autoclass:: asyncpraw.models.RedditorList - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/redditorstream.rst b/docs/code_overview/other/redditorstream.rst index 0a1b44a49..78c8b59c8 100644 --- a/docs/code_overview/other/redditorstream.rst +++ b/docs/code_overview/other/redditorstream.rst @@ -2,4 +2,4 @@ RedditorStream ============== .. autoclass:: asyncpraw.models.reddit.redditor.RedditorStream - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/removalreason.rst b/docs/code_overview/other/removalreason.rst index f0622d297..dfeae7d81 100644 --- a/docs/code_overview/other/removalreason.rst +++ b/docs/code_overview/other/removalreason.rst @@ -2,4 +2,4 @@ RemovalReason ============= .. autoclass:: asyncpraw.models.reddit.removal_reasons.RemovalReason - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/rule.rst b/docs/code_overview/other/rule.rst index 6e1fc9619..a15847977 100644 --- a/docs/code_overview/other/rule.rst +++ b/docs/code_overview/other/rule.rst @@ -2,6 +2,6 @@ Rule ==== .. autoclass:: asyncpraw.models.Rule - :inherited-members: + :inherited-members: .. include:: ../models/note_dynamically_provided_attributes.txt diff --git a/docs/code_overview/other/rulemoderation.rst b/docs/code_overview/other/rulemoderation.rst index 2ba3b4f00..b140c0578 100644 --- a/docs/code_overview/other/rulemoderation.rst +++ b/docs/code_overview/other/rulemoderation.rst @@ -2,4 +2,4 @@ RuleModeration ============== .. autoclass:: asyncpraw.models.reddit.rules.RuleModeration - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/ruleswidget.rst b/docs/code_overview/other/ruleswidget.rst index b39dd7f1b..46568bb14 100755 --- a/docs/code_overview/other/ruleswidget.rst +++ b/docs/code_overview/other/ruleswidget.rst @@ -1,6 +1,7 @@ RulesWidget =========== + .. autoclass:: asyncpraw.models.RulesWidget - :inherited-members: + :inherited-members: .. include:: ../models/note_dynamically_provided_attributes.txt diff --git a/docs/code_overview/other/styles.rst b/docs/code_overview/other/styles.rst index c83ed65fb..b7e39bf17 100644 --- a/docs/code_overview/other/styles.rst +++ b/docs/code_overview/other/styles.rst @@ -1,4 +1,5 @@ Styles ====== + .. autoclass:: asyncpraw.models.Styles - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/stylesheet.rst b/docs/code_overview/other/stylesheet.rst index ed395ae8a..5f4b439a0 100644 --- a/docs/code_overview/other/stylesheet.rst +++ b/docs/code_overview/other/stylesheet.rst @@ -2,4 +2,4 @@ Stylesheet ========== .. autoclass:: asyncpraw.models.Stylesheet - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/sublisting.rst b/docs/code_overview/other/sublisting.rst index 723f1135e..65324e1b8 100644 --- a/docs/code_overview/other/sublisting.rst +++ b/docs/code_overview/other/sublisting.rst @@ -2,4 +2,4 @@ SubListing ========== .. autoclass:: asyncpraw.models.listing.mixins.redditor.SubListing - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/submenu.rst b/docs/code_overview/other/submenu.rst index b9cf373e7..53300a98d 100755 --- a/docs/code_overview/other/submenu.rst +++ b/docs/code_overview/other/submenu.rst @@ -2,4 +2,4 @@ Submenu ======= .. autoclass:: asyncpraw.models.Submenu - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/submissionflair.rst b/docs/code_overview/other/submissionflair.rst index 78d98ef35..e93578c82 100644 --- a/docs/code_overview/other/submissionflair.rst +++ b/docs/code_overview/other/submissionflair.rst @@ -2,4 +2,4 @@ SubmissionFlair =============== .. autoclass:: asyncpraw.models.reddit.submission.SubmissionFlair - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/submissionmoderation.rst b/docs/code_overview/other/submissionmoderation.rst index 2263d5a77..2084a5c6f 100644 --- a/docs/code_overview/other/submissionmoderation.rst +++ b/docs/code_overview/other/submissionmoderation.rst @@ -2,4 +2,4 @@ SubmissionModeration ==================== .. autoclass:: asyncpraw.models.reddit.submission.SubmissionModeration - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/subredditcollections.rst b/docs/code_overview/other/subredditcollections.rst index 72a0c1818..330e5da05 100644 --- a/docs/code_overview/other/subredditcollections.rst +++ b/docs/code_overview/other/subredditcollections.rst @@ -1,4 +1,5 @@ SubredditCollections ==================== + .. autoclass:: asyncpraw.models.reddit.collections.SubredditCollections - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/subredditcollectionsmoderation.rst b/docs/code_overview/other/subredditcollectionsmoderation.rst index b197795e2..c07d8e27e 100644 --- a/docs/code_overview/other/subredditcollectionsmoderation.rst +++ b/docs/code_overview/other/subredditcollectionsmoderation.rst @@ -1,4 +1,5 @@ SubredditCollectionsModeration ============================== + .. autoclass:: asyncpraw.models.reddit.collections.SubredditCollectionsModeration - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/subredditemoji.rst b/docs/code_overview/other/subredditemoji.rst index f10eda08b..42423f9de 100644 --- a/docs/code_overview/other/subredditemoji.rst +++ b/docs/code_overview/other/subredditemoji.rst @@ -2,4 +2,4 @@ SubredditEmoji ============== .. autoclass:: asyncpraw.models.reddit.emoji.SubredditEmoji - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/subredditfilters.rst b/docs/code_overview/other/subredditfilters.rst index 91a957b0c..3d226ae2b 100644 --- a/docs/code_overview/other/subredditfilters.rst +++ b/docs/code_overview/other/subredditfilters.rst @@ -2,4 +2,4 @@ SubredditFilters ================ .. autoclass:: asyncpraw.models.reddit.subreddit.SubredditFilters - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/subredditflair.rst b/docs/code_overview/other/subredditflair.rst index 2733bdaa5..fb698917a 100644 --- a/docs/code_overview/other/subredditflair.rst +++ b/docs/code_overview/other/subredditflair.rst @@ -2,4 +2,4 @@ SubredditFlair ============== .. autoclass:: asyncpraw.models.reddit.subreddit.SubredditFlair - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/subredditflairtemplates.rst b/docs/code_overview/other/subredditflairtemplates.rst index dad8d67b9..be4fb65f7 100644 --- a/docs/code_overview/other/subredditflairtemplates.rst +++ b/docs/code_overview/other/subredditflairtemplates.rst @@ -2,4 +2,4 @@ SubredditFlairTemplates ======================= .. autoclass:: asyncpraw.models.reddit.subreddit.SubredditFlairTemplates - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/subredditlinkflairtemplates.rst b/docs/code_overview/other/subredditlinkflairtemplates.rst index 8fad1bdf6..1c4b00d8e 100644 --- a/docs/code_overview/other/subredditlinkflairtemplates.rst +++ b/docs/code_overview/other/subredditlinkflairtemplates.rst @@ -2,4 +2,4 @@ SubredditLinkFlairTemplates =========================== .. autoclass:: asyncpraw.models.reddit.subreddit.SubredditLinkFlairTemplates - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/subredditmessage.rst b/docs/code_overview/other/subredditmessage.rst index 745d64dab..a3dfd1eb3 100644 --- a/docs/code_overview/other/subredditmessage.rst +++ b/docs/code_overview/other/subredditmessage.rst @@ -2,4 +2,4 @@ SubredditMessage ================ .. autoclass:: asyncpraw.models.SubredditMessage - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/subredditmoderation.rst b/docs/code_overview/other/subredditmoderation.rst index 6a237892b..52137d6a9 100644 --- a/docs/code_overview/other/subredditmoderation.rst +++ b/docs/code_overview/other/subredditmoderation.rst @@ -2,4 +2,4 @@ SubredditModeration =================== .. autoclass:: asyncpraw.models.reddit.subreddit.SubredditModeration - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/subredditmoderationstream.rst b/docs/code_overview/other/subredditmoderationstream.rst index 00ed381a8..2f232ef13 100644 --- a/docs/code_overview/other/subredditmoderationstream.rst +++ b/docs/code_overview/other/subredditmoderationstream.rst @@ -2,4 +2,4 @@ SubredditModerationStream ========================= .. autoclass:: asyncpraw.models.reddit.subreddit.SubredditModerationStream - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/subredditquarantine.rst b/docs/code_overview/other/subredditquarantine.rst index abc89dd0f..6efa7d4f4 100644 --- a/docs/code_overview/other/subredditquarantine.rst +++ b/docs/code_overview/other/subredditquarantine.rst @@ -2,4 +2,4 @@ SubredditQuarantine =================== .. autoclass:: asyncpraw.models.reddit.subreddit.SubredditQuarantine - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/subredditredditorflairtemplates.rst b/docs/code_overview/other/subredditredditorflairtemplates.rst index dadf439d4..5557131e4 100644 --- a/docs/code_overview/other/subredditredditorflairtemplates.rst +++ b/docs/code_overview/other/subredditredditorflairtemplates.rst @@ -2,4 +2,4 @@ SubredditRedditorFlairTemplates =============================== .. autoclass:: asyncpraw.models.reddit.subreddit.SubredditRedditorFlairTemplates - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/subredditrelationship.rst b/docs/code_overview/other/subredditrelationship.rst index ce2177a45..ed68ee3f6 100644 --- a/docs/code_overview/other/subredditrelationship.rst +++ b/docs/code_overview/other/subredditrelationship.rst @@ -2,4 +2,4 @@ SubredditRelationship ===================== .. autoclass:: asyncpraw.models.reddit.subreddit.SubredditRelationship - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/subredditremovalreasons.rst b/docs/code_overview/other/subredditremovalreasons.rst index c68d391d7..bb27e6287 100644 --- a/docs/code_overview/other/subredditremovalreasons.rst +++ b/docs/code_overview/other/subredditremovalreasons.rst @@ -2,4 +2,4 @@ SubredditRemovalReasons ======================= .. autoclass:: asyncpraw.models.reddit.removal_reasons.SubredditRemovalReasons - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/subredditrules.rst b/docs/code_overview/other/subredditrules.rst index 59d043889..d8605c227 100644 --- a/docs/code_overview/other/subredditrules.rst +++ b/docs/code_overview/other/subredditrules.rst @@ -2,4 +2,4 @@ SubredditRules ============== .. autoclass:: asyncpraw.models.reddit.rules.SubredditRules - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/subredditrulesmoderation.rst b/docs/code_overview/other/subredditrulesmoderation.rst index 7fbccdfbb..783858578 100644 --- a/docs/code_overview/other/subredditrulesmoderation.rst +++ b/docs/code_overview/other/subredditrulesmoderation.rst @@ -2,4 +2,4 @@ SubredditRulesModeration ======================== .. autoclass:: asyncpraw.models.reddit.rules.SubredditRulesModeration - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/subredditstream.rst b/docs/code_overview/other/subredditstream.rst index 9cda2e5fa..158b8789c 100644 --- a/docs/code_overview/other/subredditstream.rst +++ b/docs/code_overview/other/subredditstream.rst @@ -2,4 +2,4 @@ SubredditStream =============== .. autoclass:: asyncpraw.models.reddit.subreddit.SubredditStream - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/subredditstylesheet.rst b/docs/code_overview/other/subredditstylesheet.rst index a8b198a0d..b2ddc807a 100644 --- a/docs/code_overview/other/subredditstylesheet.rst +++ b/docs/code_overview/other/subredditstylesheet.rst @@ -2,4 +2,4 @@ SubredditStylesheet =================== .. autoclass:: asyncpraw.models.reddit.subreddit.SubredditStylesheet - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/subredditwidgets.rst b/docs/code_overview/other/subredditwidgets.rst index b297ebfbc..946e91eeb 100755 --- a/docs/code_overview/other/subredditwidgets.rst +++ b/docs/code_overview/other/subredditwidgets.rst @@ -2,4 +2,4 @@ SubredditWidgets ================ .. autoclass:: asyncpraw.models.SubredditWidgets - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/subredditwidgetsmoderation.rst b/docs/code_overview/other/subredditwidgetsmoderation.rst index b122820f6..590741dfa 100644 --- a/docs/code_overview/other/subredditwidgetsmoderation.rst +++ b/docs/code_overview/other/subredditwidgetsmoderation.rst @@ -2,4 +2,4 @@ SubredditWidgetsModeration ========================== .. autoclass:: asyncpraw.models.SubredditWidgetsModeration - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/subredditwiki.rst b/docs/code_overview/other/subredditwiki.rst index d6960aa6e..005bcb713 100644 --- a/docs/code_overview/other/subredditwiki.rst +++ b/docs/code_overview/other/subredditwiki.rst @@ -2,4 +2,4 @@ SubredditWiki ============= .. autoclass:: asyncpraw.models.reddit.subreddit.SubredditWiki - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/textarea.rst b/docs/code_overview/other/textarea.rst index 63bef850c..147368cf6 100755 --- a/docs/code_overview/other/textarea.rst +++ b/docs/code_overview/other/textarea.rst @@ -1,6 +1,7 @@ TextArea ======== + .. autoclass:: asyncpraw.models.TextArea - :inherited-members: + :inherited-members: .. include:: ../models/note_dynamically_provided_attributes.txt diff --git a/docs/code_overview/other/thingmoderationmixin.rst b/docs/code_overview/other/thingmoderationmixin.rst index cc6996ce5..f42a02308 100644 --- a/docs/code_overview/other/thingmoderationmixin.rst +++ b/docs/code_overview/other/thingmoderationmixin.rst @@ -2,4 +2,4 @@ ThingModerationMixin ==================== .. autoclass:: asyncpraw.models.reddit.mixins.ThingModerationMixin - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/token_manager.rst b/docs/code_overview/other/token_manager.rst index 07acc5a0e..f2ad5dee6 100644 --- a/docs/code_overview/other/token_manager.rst +++ b/docs/code_overview/other/token_manager.rst @@ -2,4 +2,4 @@ Token Manager ============= .. automodule:: asyncpraw.util.token_manager - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/trophy.rst b/docs/code_overview/other/trophy.rst index 2a348e174..88cac177f 100644 --- a/docs/code_overview/other/trophy.rst +++ b/docs/code_overview/other/trophy.rst @@ -1,4 +1,5 @@ Trophy ====== + .. autoclass:: asyncpraw.models.Trophy - :members: __str__ + :members: __str__ diff --git a/docs/code_overview/other/util.rst b/docs/code_overview/other/util.rst index 4a7a301a3..31edebd95 100644 --- a/docs/code_overview/other/util.rst +++ b/docs/code_overview/other/util.rst @@ -2,10 +2,10 @@ Util ==== .. autoclass:: asyncpraw.models.util.BoundedSet - :inherited-members: + :inherited-members: .. autoclass:: asyncpraw.models.util.ExponentialCounter - :inherited-members: + :inherited-members: .. autofunction:: asyncpraw.models.util.permissions_string diff --git a/docs/code_overview/other/widgetmoderation.rst b/docs/code_overview/other/widgetmoderation.rst index ccaf2995f..de9874613 100644 --- a/docs/code_overview/other/widgetmoderation.rst +++ b/docs/code_overview/other/widgetmoderation.rst @@ -2,4 +2,4 @@ WidgetModeration ================ .. autoclass:: asyncpraw.models.WidgetModeration - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/other/wikipagemoderation.rst b/docs/code_overview/other/wikipagemoderation.rst index 0e3cc9970..27fddf10e 100644 --- a/docs/code_overview/other/wikipagemoderation.rst +++ b/docs/code_overview/other/wikipagemoderation.rst @@ -2,4 +2,4 @@ WikiPageModeration ================== .. autoclass:: asyncpraw.models.reddit.wikipage.WikiPageModeration - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/reddit/front.rst b/docs/code_overview/reddit/front.rst index 9c0996635..9c8badef8 100644 --- a/docs/code_overview/reddit/front.rst +++ b/docs/code_overview/reddit/front.rst @@ -2,4 +2,4 @@ reddit.front ============ .. autoclass:: asyncpraw.models.Front - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/reddit/inbox.rst b/docs/code_overview/reddit/inbox.rst index 10d621883..f4533511d 100644 --- a/docs/code_overview/reddit/inbox.rst +++ b/docs/code_overview/reddit/inbox.rst @@ -2,4 +2,4 @@ reddit.inbox ============ .. autoclass:: asyncpraw.models.Inbox - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/reddit/live.rst b/docs/code_overview/reddit/live.rst index 21d57002e..8f9fa36ec 100644 --- a/docs/code_overview/reddit/live.rst +++ b/docs/code_overview/reddit/live.rst @@ -2,4 +2,4 @@ reddit.live =========== .. autoclass:: asyncpraw.models.LiveHelper - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/reddit/multireddit.rst b/docs/code_overview/reddit/multireddit.rst index 21c36e9f8..b94f6951b 100644 --- a/docs/code_overview/reddit/multireddit.rst +++ b/docs/code_overview/reddit/multireddit.rst @@ -2,4 +2,4 @@ reddit.multireddit ================== .. autoclass:: asyncpraw.models.MultiredditHelper - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/reddit/redditors.rst b/docs/code_overview/reddit/redditors.rst index bc46debda..68600ae04 100644 --- a/docs/code_overview/reddit/redditors.rst +++ b/docs/code_overview/reddit/redditors.rst @@ -2,4 +2,4 @@ reddit.redditors ================ .. autoclass:: asyncpraw.models.Redditors - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/reddit/subreddit.rst b/docs/code_overview/reddit/subreddit.rst index bec803fea..02b79cd85 100644 --- a/docs/code_overview/reddit/subreddit.rst +++ b/docs/code_overview/reddit/subreddit.rst @@ -2,4 +2,4 @@ reddit.subreddit ================ .. autoclass:: asyncpraw.models.SubredditHelper - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/reddit/subreddits.rst b/docs/code_overview/reddit/subreddits.rst index 28faa8ae0..4f56a947b 100644 --- a/docs/code_overview/reddit/subreddits.rst +++ b/docs/code_overview/reddit/subreddits.rst @@ -2,4 +2,4 @@ reddit.subreddits ================= .. autoclass:: asyncpraw.models.Subreddits - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/reddit/user.rst b/docs/code_overview/reddit/user.rst index d890605e7..7a9f06b5d 100644 --- a/docs/code_overview/reddit/user.rst +++ b/docs/code_overview/reddit/user.rst @@ -2,4 +2,4 @@ reddit.user =========== .. autoclass:: asyncpraw.models.User - :inherited-members: + :inherited-members: diff --git a/docs/code_overview/reddit_instance.rst b/docs/code_overview/reddit_instance.rst index cd4a1b0d3..23aa5c69e 100644 --- a/docs/code_overview/reddit_instance.rst +++ b/docs/code_overview/reddit_instance.rst @@ -2,17 +2,17 @@ The Reddit Instance =================== .. autoclass:: asyncpraw.Reddit - :inherited-members: + :inherited-members: .. toctree:: - :maxdepth: 2 - :caption: Helper Classes + :maxdepth: 2 + :caption: Helper Classes - reddit/front - reddit/inbox - reddit/live - reddit/multireddit - reddit/redditors - reddit/subreddit - reddit/subreddits - reddit/user + reddit/front + reddit/inbox + reddit/live + reddit/multireddit + reddit/redditors + reddit/subreddit + reddit/subreddits + reddit/user diff --git a/docs/getting_started/authentication.rst b/docs/getting_started/authentication.rst index e125cf646..c488ceea3 100644 --- a/docs/getting_started/authentication.rst +++ b/docs/getting_started/authentication.rst @@ -3,21 +3,24 @@ Authenticating via OAuth ======================== -Async PRAW supports all three types of applications that can be registered on -Reddit. Those are: +Async PRAW supports all three types of applications that can be registered on Reddit. +Those are: -* `Web Applications `_ -* `Installed Applications `_ -* `Script Applications `_ +- `Web Applications + `_ +- `Installed Applications + `_ +- `Script Applications + `_ Before you can use any one of these with Async PRAW, you must first `register -`_ an application of the appropriate type -on Reddit. +`_ an application of the appropriate type on Reddit. -If your application does not require a user context, it is :ref:`read-only `. +If your application does not require a user context, it is :ref:`read-only +`. -Async PRAW supports the flows that each of these applications can use. The -following table defines which application types can use which flows: +Async PRAW supports the flows that each of these applications can use. The following +table defines which application types can use which flows: .. include:: authentication_flow_table.txt @@ -26,55 +29,56 @@ following table defines which application types can use which flows: Password Flow ------------- -**Password Flow** is the simplest type of authentication flow to work with -because no callback process is involved in obtaining an ``access_token``. +**Password Flow** is the simplest type of authentication flow to work with because no +callback process is involved in obtaining an ``access_token``. -While **password flow** applications do not involve a redirect URI, Reddit -still requires that you provide one when registering your script application -- +While **password flow** applications do not involve a redirect URI, Reddit still +requires that you provide one when registering your script application -- ``http://localhost:8080`` is a simple one to use. -In order to use a **password flow** application with Async PRAW you need four pieces -of information: - -:client_id: The client ID is the 14-character string listed just under - "personal use script" for the desired `developed application - `_ +In order to use a **password flow** application with Async PRAW you need four pieces of +information: +:client_id: The client ID is the 14-character string listed just under "personal use + script" for the desired `developed application + `_ :client_secret: The client secret is at least a 27-character string listed adjacent to - ``secret`` for the application. - + ``secret`` for the application. :password: The password for the Reddit account used to register the application. - :username: The username of the Reddit account used to register the application. -With this information authorizing as ``username`` using a **password flow** app -is as simple as: +With this information authorizing as ``username`` using a **password flow** app is as +simple as: .. code-block:: python - reddit = asyncpraw.Reddit(client_id="SI8pN3DSbt0zor", - client_secret="xaxkj7HNh8kwg8e5t4m6KvSrbTI", - password="1guiwevlfo00esyy", - user_agent="testscript by u/fakebot3", - username="fakebot3") + reddit = asyncpraw.Reddit( + client_id="SI8pN3DSbt0zor", + client_secret="xaxkj7HNh8kwg8e5t4m6KvSrbTI", + password="1guiwevlfo00esyy", + user_agent="testscript by u/fakebot3", + username="fakebot3", + ) To verify that you are authenticated as the correct user run: .. code-block:: python - print(await reddit.user.me()) + print(await reddit.user.me()) The output should contain the same name as you entered for ``username``. -.. note:: If the following exception is raised, double-check your credentials, - and ensure that that the username and password you are using are for - the same user with which the application is associated: +.. note:: + + If the following exception is raised, double-check your credentials, and ensure that + that the username and password you are using are for the same user with which the + application is associated: - .. code-block:: text + .. code-block:: text - OAuthException: invalid_grant error processing request + OAuthException: invalid_grant error processing request -.. _2FA: +.. _2fa: Two-Factor Authentication ~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -83,20 +87,21 @@ A 2FA token can be used by joining it to the password with a colon: .. code-block:: python - reddit = asyncpraw.Reddit(client_id="SI8pN3DSbt0zor", - client_secret="xaxkj7HNh8kwg8e5t4m6KvSrbTI", - password='1guiwevlfo00esyy:955413', - user_agent="testscript by u/fakebot3", - username="fakebot3") + reddit = asyncpraw.Reddit( + client_id="SI8pN3DSbt0zor", + client_secret="xaxkj7HNh8kwg8e5t4m6KvSrbTI", + password="1guiwevlfo00esyy:955413", + user_agent="testscript by u/fakebot3", + username="fakebot3", + ) -However, for such an app there is little benefit to using 2FA. The token -must be refreshed after one hour; therefore, the 2FA secret would have to be -stored along with the rest of the credentials in order to generate the token, -which defeats the point of having an extra credential beyond the password. - -If you do choose to use 2FA, you must handle the ``asyncprawcore.OAuthException`` -that will be raised by API calls after one hour. +However, for such an app there is little benefit to using 2FA. The token must be +refreshed after one hour; therefore, the 2FA secret would have to be stored along with +the rest of the credentials in order to generate the token, which defeats the point of +having an extra credential beyond the password. +If you do choose to use 2FA, you must handle the ``asyncprawcore.OAuthException`` that +will be raised by API calls after one hour. .. _code_flow: @@ -105,21 +110,20 @@ Code Flow A **code flow** application is useful for two primary purposes: -* You have an application and want to be able to access Reddit from your users' +- You have an application and want to be able to access Reddit from your users' accounts. -* You have a personal-use script application and you either want to +- You have a personal-use script application and you either want to - * limit the access one of your Async PRAW-based programs has to Reddit - * avoid the hassle of 2FA (described above) - * not pass your username and password to Async PRAW (and thus not keep it in memory) + - limit the access one of your Async PRAW-based programs has to Reddit + - avoid the hassle of 2FA (described above) + - not pass your username and password to Async PRAW (and thus not keep it in memory) -When registering your application you must provide a valid redirect URI. If you -are running a website you will want to enter the appropriate callback URL and -configure that endpoint to complete the code flow. +When registering your application you must provide a valid redirect URI. If you are +running a website you will want to enter the appropriate callback URL and configure that +endpoint to complete the code flow. If you aren't actually running a website, you can follow the :ref:`refresh_token` -tutorial to learn how to obtain and use the -initial refresh token. +tutorial to learn how to obtain and use the initial refresh token. Whether or not you follow the :ref:`refresh_token` tutorial there are two processes involved in obtaining access or refresh tokens. @@ -129,57 +133,57 @@ involved in obtaining access or refresh tokens. Obtain the Authorization URL ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The first step to completing the **code flow** is to obtain the authorization -URL. You can do that as follows: +The first step to completing the **code flow** is to obtain the authorization URL. You +can do that as follows: .. code-block:: python - reddit = asyncpraw.Reddit(client_id="SI8pN3DSbt0zor", - client_secret="xaxkj7HNh8kwg8e5t4m6KvSrbTI", - redirect_uri="http://localhost:8080", - user_agent="testscript by u/fakebot3") - print(reddit.auth.url(["identity"], "...", "permanent")) + reddit = asyncpraw.Reddit( + client_id="SI8pN3DSbt0zor", + client_secret="xaxkj7HNh8kwg8e5t4m6KvSrbTI", + redirect_uri="http://localhost:8080", + user_agent="testscript by u/fakebot3", + ) + print(reddit.auth.url(["identity"], "...", "permanent")) The above will output an authorization URL for a permanent token (i.e., the resulting -authorization will include both a short-lived ``access_token``, and a longer-lived, single -use ``refresh_token``)that has only -the ``identity`` scope. See :meth:`.url` for more information on these -parameters. +authorization will include both a short-lived ``access_token``, and a longer-lived, +single use ``refresh_token``)that has only the ``identity`` scope. See :meth:`.url` for +more information on these parameters. -This URL should be accessed by the account that desires to authorize their -Reddit access to your application. On completion of that flow, the user's -browser will be redirected to the specified ``redirect_uri``. After -verifying the ``state`` and extracting the ``code`` you can obtain the refresh -token via: +This URL should be accessed by the account that desires to authorize their Reddit access +to your application. On completion of that flow, the user's browser will be redirected +to the specified ``redirect_uri``. After verifying the ``state`` and extracting the +``code`` you can obtain the refresh token via: .. code-block:: python print(await reddit.auth.authorize(code)) print(await reddit.user.me()) -The first line of output is the ``refresh_token``. You can save this for later -use (see :ref:`using_refresh_tokens`). +The first line of output is the ``refresh_token``. You can save this for later use (see +:ref:`using_refresh_tokens`). -The second line of output reveals the name of the Redditor that completed the -code flow. It also indicates that the :class:`.Reddit` instance is now associated -with that account. +The second line of output reveals the name of the Redditor that completed the code flow. +It also indicates that the :class:`.Reddit` instance is now associated with that +account. -The code flow can be used with an **installed** application just as described -above with one change: set the value of ``client_secret`` to ``None`` when -initializing :class:`.Reddit`. +The code flow can be used with an **installed** application just as described above with +one change: set the value of ``client_secret`` to ``None`` when initializing +:class:`.Reddit`. .. _implicit_flow: Implicit Flow ------------- -The **implicit flow** requires a similar instantiation of the :class:`.Reddit` -class as done in :ref:`code_flow`, however, the token is returned directly as -part of the redirect. For the implicit flow call :meth:`.url` like so: +The **implicit flow** requires a similar instantiation of the :class:`.Reddit` class as +done in :ref:`code_flow`, however, the token is returned directly as part of the +redirect. For the implicit flow call :meth:`.url` like so: .. code-block:: python - print(reddit.auth.url(["identity"], "...", implicit=True)) + print(reddit.auth.url(["identity"], "...", implicit=True)) Then use :meth:`.implicit` to provide the authorization to the :class:`.Reddit` instance. @@ -189,26 +193,24 @@ instance. Read-Only Mode -------------- -All application types support a read-only mode. Read-only mode provides access -to Reddit like a logged out user would see including the default Subreddits in -the ``reddit.front`` listings. +All application types support a read-only mode. Read-only mode provides access to Reddit +like a logged out user would see including the default Subreddits in the +``reddit.front`` listings. -In the absence of a ``refresh_token`` both :ref:`code_flow` and -:ref:`implicit_flow` applications start in the **read-only** mode. With such -applications **read-only** mode is disabled when :meth:`.authorize`, or -:meth:`.implicit` are successfully called. :ref:`password_flow` applications -start up with **read-only** mode disabled. +In the absence of a ``refresh_token`` both :ref:`code_flow` and :ref:`implicit_flow` +applications start in the **read-only** mode. With such applications **read-only** mode +is disabled when :meth:`.authorize`, or :meth:`.implicit` are successfully called. +:ref:`password_flow` applications start up with **read-only** mode disabled. Read-only mode can be toggled via: .. code-block:: python - # Enable read-only mode - reddit.read_only = True - - # Disable read-only mode (must have a valid authorization) - reddit.read_only = False + # Enable read-only mode + reddit.read_only = True + # Disable read-only mode (must have a valid authorization) + reddit.read_only = False Application-Only Flows ~~~~~~~~~~~~~~~~~~~~~~ @@ -220,29 +222,30 @@ The following flows are the **read-only mode** flows for Reddit applications Application-Only (Client Credentials) +++++++++++++++++++++++++++++++++++++ -This is the default flow for **read-only mode** in script and web applications. -The idea behind this is that Reddit *can* trust these applications as coming from -a given developer, however the application requires no logged-in user context. +This is the default flow for **read-only mode** in script and web applications. The idea +behind this is that Reddit *can* trust these applications as coming from a given +developer, however the application requires no logged-in user context. An installed application *cannot* use this flow, because Reddit requires a -``client_secret`` to be given it this flow is being used. In other words, -installed applications are not considered confidential clients. +``client_secret`` to be given it this flow is being used. In other words, installed +applications are not considered confidential clients. .. _application_only_installed_client_flow: Application-Only (Installed Client) +++++++++++++++++++++++++++++++++++ -This is the default flow for **read-only mode** in installed applications. -The idea behind this is that Reddit *might not be able* to trust these -applications as coming from a given developer. This would be able to happen if -someone other than the developer can potentially replicate the client information -and then pretend to be the application, such as in installed applications where -the end user could retrieve the ``client_id``. - -.. note:: No benefit is really gained from this in script or web apps. - The one exception is for when a script or web app has multiple end users, this - will allow you to give Reddit the information needed in order to distinguish - different users of your app from each other (as the supplied device id *should* - be a unique string per both device (in the case of a web app, server) and user - (in the case of a web app, browser session). +This is the default flow for **read-only mode** in installed applications. The idea +behind this is that Reddit *might not be able* to trust these applications as coming +from a given developer. This would be able to happen if someone other than the developer +can potentially replicate the client information and then pretend to be the application, +such as in installed applications where the end user could retrieve the ``client_id``. + +.. note:: + + No benefit is really gained from this in script or web apps. The one exception is + for when a script or web app has multiple end users, this will allow you to give + Reddit the information needed in order to distinguish different users of your app + from each other (as the supplied device id *should* be a unique string per both + device (in the case of a web app, server) and user (in the case of a web app, + browser session). diff --git a/docs/getting_started/configuration.rst b/docs/getting_started/configuration.rst index ae2c07592..f44be8694 100644 --- a/docs/getting_started/configuration.rst +++ b/docs/getting_started/configuration.rst @@ -8,47 +8,45 @@ Configuring Async PRAW Async PRAW is fully compatible with the configuration system that PRAW uses. .. toctree:: - :maxdepth: 2 - - configuration/options + :maxdepth: 2 + configuration/options Configuration options can be provided to Async PRAW in one of three ways: .. toctree:: - :maxdepth: 1 + :maxdepth: 1 - configuration/prawini - configuration/reddit_initialization - configuration/environment_variables + configuration/prawini + configuration/reddit_initialization + configuration/environment_variables -Environment variables have the highest priority, followed by keyword arguments -to :class:`.Reddit`, and finally settings in ``praw.ini`` files. +Environment variables have the highest priority, followed by keyword arguments to +:class:`.Reddit`, and finally settings in ``praw.ini`` files. .. _proxy-support: Using an HTTP or HTTPS proxy with Async PRAW -------------------------------------------- -Async PRAW internally relies upon the `aiohttp `_ -package to handle HTTP requests. Aiohttp supports use of ``HTTP_PROXY`` and -``HTTPS_PROXY`` environment variables in order to proxy HTTP and HTTPS requests -respectively [`ref +Async PRAW internally relies upon the `aiohttp `_ package to +handle HTTP requests. Aiohttp supports use of ``HTTP_PROXY`` and ``HTTPS_PROXY`` +environment variables in order to proxy HTTP and HTTPS requests respectively [`ref `_]. Given that Async PRAW exclusively communicates with Reddit via HTTPS, only the ``HTTPS_PROXY`` option should be required. -For example, if you have a script named ``prawbot.py``, the ``HTTPS_PROXY`` -environment variable can be provided on the command line like so: +For example, if you have a script named ``prawbot.py``, the ``HTTPS_PROXY`` environment +variable can be provided on the command line like so: .. code-block:: bash - HTTPS_PROXY=http://localhost:3128 ./prawbot.py + HTTPS_PROXY=http://localhost:3128 ./prawbot.py -Contrary to the Requests library, aiohttp won’t read environment -variables by default. But you can do so by passing ``trust_env=True`` into -aiohttp and configuring Async PRAW like so: +Contrary to the Requests library, aiohttp won’t read environment variables by default. +But you can do so by passing ``trust_env=True`` into aiohttp and configuring Async PRAW +like so: .. code-block:: python @@ -57,27 +55,27 @@ aiohttp and configuring Async PRAW like so: session = ClientSession(trust_env=True) - reddit = asyncpraw.Reddit(client_id="SI8pN3DSbt0zor", - client_secret="xaxkj7HNh8kwg8e5t4m6KvSrbTI", - password="1guiwevlfo00esyy", - requestor_kwargs={"session": session}, # pass Session - user_agent="testscript by u/fakebot3", - username="fakebot3") - + reddit = asyncpraw.Reddit( + client_id="SI8pN3DSbt0zor", + client_secret="xaxkj7HNh8kwg8e5t4m6KvSrbTI", + password="1guiwevlfo00esyy", + requestor_kwargs={"session": session}, # pass Session + user_agent="testscript by u/fakebot3", + username="fakebot3", + ) Configuring a custom aiohttp ClientSession ------------------------------------------ -Async PRAW uses `aiohttp`_ to handle -networking. If your use-case requires custom configuration, it is possible to -configure a `ClientSession -`_ and then use it with -Async PRAW. +Async PRAW uses aiohttp_ to handle networking. If your use-case requires custom +configuration, it is possible to configure a `ClientSession +`_ and then use it with Async +PRAW. -For example, some networks use self-signed SSL certificates when connecting -to HTTPS sites. By default, this would raise an exception in Aiohttp. To -use a self-signed SSL certificate without an exception from Aiohttp, first -export the certificate as a ``.pem`` file. Then configure Async PRAW like so: +For example, some networks use self-signed SSL certificates when connecting to HTTPS +sites. By default, this would raise an exception in Aiohttp. To use a self-signed SSL +certificate without an exception from Aiohttp, first export the certificate as a +``.pem`` file. Then configure Async PRAW like so: .. code-block:: python @@ -91,16 +89,18 @@ export the certificate as a ``.pem`` file. Then configure Async PRAW like so: conn = aiohttp.TCPConnector(ssl_context=ssl_ctx) session = aiohttp.ClientSession(connector=conn) - reddit = asyncpraw.Reddit(client_id="SI8pN3DSbt0zor", - client_secret="xaxkj7HNh8kwg8e5t4m6KvSrbTI", - password="1guiwevlfo00esyy", - requestor_kwargs={"session": session}, # pass Session - user_agent="testscript by u/fakebot3", - username="fakebot3") - - -The code above creates a ``ClientSession`` and `configures it to use a custom certificate + reddit = asyncpraw.Reddit( + client_id="SI8pN3DSbt0zor", + client_secret="xaxkj7HNh8kwg8e5t4m6KvSrbTI", + password="1guiwevlfo00esyy", + requestor_kwargs={"session": session}, # pass Session + user_agent="testscript by u/fakebot3", + username="fakebot3", + ) + +The code above creates a ``ClientSession`` and `configures it to use a custom +certificate `_, -then passes it as a parameter when creating the :class:`.Reddit` instance. -Note that the example above uses a :ref:`password_flow` authentication type, -but this method will work for any authentication type. +then passes it as a parameter when creating the :class:`.Reddit` instance. Note that the +example above uses a :ref:`password_flow` authentication type, but this method will work +for any authentication type. diff --git a/docs/getting_started/configuration/environment_variables.rst b/docs/getting_started/configuration/environment_variables.rst index c59a5f7b5..86be7cd07 100644 --- a/docs/getting_started/configuration/environment_variables.rst +++ b/docs/getting_started/configuration/environment_variables.rst @@ -3,18 +3,18 @@ Async PRAW Environment Variables ================================ -The second-highest priority configuration options can be passed to a program -via environment variables prefixed with ``praw_``. +The second-highest priority configuration options can be passed to a program via +environment variables prefixed with ``praw_``. For example, you can invoke your script as follows: .. code-block:: shell - praw_username=bboe praw_password=not_my_password python my_script.py + praw_username=bboe praw_password=not_my_password python my_script.py -The ``username`` and ``password`` provided via environment variables will -override any values contained in a ``praw.ini`` file., but not any variables -passed in through :class:`.Reddit`. +The ``username`` and ``password`` provided via environment variables will override any +values contained in a ``praw.ini`` file., but not any variables passed in through +:class:`.Reddit`. -All :ref:`configuration_options` can be provided in this manner, except for -custom options. +All :ref:`configuration_options` can be provided in this manner, except for custom +options. diff --git a/docs/getting_started/configuration/options.rst b/docs/getting_started/configuration/options.rst index 8b6b03199..3d005b291 100644 --- a/docs/getting_started/configuration/options.rst +++ b/docs/getting_started/configuration/options.rst @@ -5,11 +5,11 @@ Configuration Options Async PRAW's configuration options are broken down into the following categories: -* :ref:`basic_options` -* :ref:`oauth_options` -* :ref:`site_options` -* :ref:`misc_options` -* :ref:`custom_options` +- :ref:`basic_options` +- :ref:`oauth_options` +- :ref:`site_options` +- :ref:`misc_options` +- :ref:`custom_options` All of these options can be provided in any of the ways mentioned in :ref:`configuration`. @@ -19,44 +19,33 @@ All of these options can be provided in any of the ways mentioned in Basic Configuration Options --------------------------- -:check_for_updates: When ``true``, check for new versions of Async PRAW. When a - newer version of Async PRAW is available a message is reported - via standard error (default: ``true``). - -:user_agent: (Required) A unique description of your application. The following - format is recommended according to `Reddit's API Rules - `_: - ``:: (by u/)``. +:check_for_updates: When ``true``, check for new versions of Async PRAW. When a newer + version of Async PRAW is available a message is reported via standard error + (default: ``true``). +:user_agent: (Required) A unique description of your application. The following format + is recommended according to `Reddit's API Rules + `_: ``:: (by u/)``. .. _oauth_options: OAuth Configuration Options --------------------------- -:client_id: (Required) The OAuth client id associated with your registered - Reddit application. See :ref:`oauth` for instructions on - registering a Reddit application. - +:client_id: (Required) The OAuth client id associated with your registered Reddit + application. See :ref:`oauth` for instructions on registering a Reddit application. :client_secret: The OAuth client secret associated with your registered Reddit - application. This option is required for all application types, - however, the value must be set to ``None`` for **installed** - applications. - -:redirect_uri: The redirect URI associated with your registered Reddit - application. This field is unused for **script** applications - and is only needed for both **web** applications, and - **installed** applications when the :meth:`.url` method is used. - -:password: The password of the Reddit account associated with your registered - Reddit **script** application. This field is required for **script** - applications, and Async PRAW assumes it is working with a **script** - application by its presence. - -:username: The username of the Reddit account associated with your registered - Reddit **script** application. This field is required for **script** - applications, and Async PRAW assumes it is working with a **script** - application by its presence. + application. This option is required for all application types, however, the value + must be set to ``None`` for **installed** applications. +:redirect_uri: The redirect URI associated with your registered Reddit application. This + field is unused for **script** applications and is only needed for both **web** + applications, and **installed** applications when the :meth:`.url` method is used. +:password: The password of the Reddit account associated with your registered Reddit + **script** application. This field is required for **script** applications, and + Async PRAW assumes it is working with a **script** application by its presence. +:username: The username of the Reddit account associated with your registered Reddit + **script** application. This field is required for **script** applications, and + Async PRAW assumes it is working with a **script** application by its presence. .. _site_options: @@ -64,72 +53,63 @@ Reddit Site Configuration Options --------------------------------- Async PRAW can be configured to work with instances of Reddit which are not hosted at -`reddit.com `_. The following options may need to be -updated in order to successfully access a third-party Reddit site: - -:comment_kind: The type prefix for comments on the Reddit instance (default: - ``t1_``). - -:message_kind: The type prefix for messages on the Reddit instance (default: - ``t4_``). +`reddit.com `_. The following options may need to be updated in +order to successfully access a third-party Reddit site: +:comment_kind: The type prefix for comments on the Reddit instance (default: ``t1_``). +:message_kind: The type prefix for messages on the Reddit instance (default: ``t4_``). :oauth_url: The URL used to access the Reddit instance's API (default: - https://oauth.reddit.com). - + https://oauth.reddit.com). :reddit_url: The URL used to access the Reddit instance. Async PRAW assumes the - endpoints for establishing OAuth authorization are accessible - under this URL (default: https://www.reddit.com). - -:redditor_kind: The type prefix for redditors on the Reddit instance (default: - ``t2_``). - -:short_url: The URL used to generate short links on the Reddit instance - (default: https://redd.it). - -:submission_kind: The type prefix for submissions on the Reddit instance - (default: ``t3_``). - -:subreddit_kind: The type prefix for subreddits on the Reddit instance - (default: ``t5_``). + endpoints for establishing OAuth authorization are accessible under this URL + (default: https://www.reddit.com). +:redditor_kind: The type prefix for redditors on the Reddit instance (default: ``t2_``). +:short_url: The URL used to generate short links on the Reddit instance (default: + https://redd.it). +:submission_kind: The type prefix for submissions on the Reddit instance (default: + ``t3_``). +:subreddit_kind: The type prefix for subreddits on the Reddit instance (default: + ``t5_``). .. _misc_options: Miscellaneous Configuration Options ----------------------------------- -These are options that do not belong in another category, but still play a part -in Async PRAW. +These are options that do not belong in another category, but still play a part in Async +PRAW. :ratelimit_seconds: Controls the maximum amount of seconds Async PRAW will capture - ratelimits returned in JSON data. Because this can be as - high as 10 minutes, only ratelimits of up to 5 seconds - are captured and waited on by default. Should be a number - representing the amount of seconds to sleep. + ratelimits returned in JSON data. Because this can be as high as 10 minutes, only + ratelimits of up to 5 seconds are captured and waited on by default. Should be a + number representing the amount of seconds to sleep. + + .. note:: - .. note:: Async PRAW sleeps for the ratelimit plus either 1/10th - of the ratelimit or 1 second, whichever is smallest. + Async PRAW sleeps for the ratelimit plus either 1/10th of the ratelimit or 1 + second, whichever is smallest. -:timeout: Controls the amount of time Async PRAW will wait for a request from Reddit - to complete before throwing an exception. By default, Async PRAW waits - 16 seconds before throwing an exception. +:timeout: Controls the amount of time Async PRAW will wait for a request from Reddit to + complete before throwing an exception. By default, Async PRAW waits 16 seconds + before throwing an exception. .. _custom_options: Custom Configuration Options ---------------------------- -Your application can utilize PRAW's configuration system in order to provide -its own custom settings. Async PRAW utilizes the the same configuration system -as PRAW. +Your application can utilize PRAW's configuration system in order to provide its own +custom settings. Async PRAW utilizes the the same configuration system as PRAW. For instance you might want to add an ``app_debugging: true`` option to your -application's ``praw.ini`` file. To retrieve the value of this custom option -from an instance of :class:`.Reddit` you can execute: +application's ``praw.ini`` file. To retrieve the value of this custom option from an +instance of :class:`.Reddit` you can execute: .. code-block:: python - reddit.config.custom["app_debugging"] + reddit.config.custom["app_debugging"] + +.. note:: -.. note:: Custom Async PRAW configuration environment variables are not - supported. You can directly access environment variables via - ``os.getenv``. + Custom Async PRAW configuration environment variables are not supported. You can + directly access environment variables via ``os.getenv``. diff --git a/docs/getting_started/configuration/prawini.rst b/docs/getting_started/configuration/prawini.rst index e2fc9f208..acd88e79a 100644 --- a/docs/getting_started/configuration/prawini.rst +++ b/docs/getting_started/configuration/prawini.rst @@ -3,156 +3,159 @@ praw.ini Files ============== -Async PRAW comes with a ``praw.ini`` file in the package directory, and looks for -user defined ``praw.ini`` files in a few other locations: +Async PRAW comes with a ``praw.ini`` file in the package directory, and looks for user +defined ``praw.ini`` files in a few other locations: 1. In the `current working directory `_ at the time :class:`.Reddit` is initialized. +2. In the launching user's config directory. This directory, if available, is detected + in order as one of the following: -2. In the launching user's config directory. This directory, if available, is - detected in order as one of the following: + 1. In the directory specified by the ``XDG_CONFIG_HOME`` environment variable on + operating systems that define such an environment variable (some modern Linux + distributions). + 2. In the directory specified by ``$HOME/.config`` if the ``HOME`` environment + variable is defined (Linux and Mac OS systems). + 3. In the directory specified by the ``APPDATA`` environment variable (Windows). - 1. In the directory specified by the ``XDG_CONFIG_HOME`` environment - variable on operating systems that define such an environment variable - (some modern Linux distributions). + .. note:: - 2. In the directory specified by ``$HOME/.config`` if the ``HOME`` - environment variable is defined (Linux and Mac OS systems). + To check the values of the environment variables, you can open up a terminal + (Terminal/Terminal.app/Command Prompt/Powershell) and echo the variables + (replacing with the name of the variable): - 3. In the directory specified by the ``APPDATA`` environment variable - (Windows). + **MacOS/Linux**: - .. note:: To check the values of the environment variables, you can - open up a terminal (Terminal/Terminal.app/Command Prompt/Powershell) - and echo the variables (replacing with the name of the - variable): + .. code-block:: bash - **MacOS/Linux**: + echo "$" - .. code-block:: bash + **Windows Command Prompt** - echo "$" + .. code-block:: bat - **Windows Command Prompt** + echo "%%" - .. code-block:: bat + **Powershell** - echo "%%" + .. code-block:: powershell - **Powershell** + Write-Output "$env:" - .. code-block:: powershell + You can also view environment variables in Python: - Write-Output "$env:" + .. code-block:: python - You can also view environment variables in Python: + import os - .. code-block:: python - - import os - print(os.environ.get("", "")) + print(os.environ.get("", "")) Format of praw.ini ------------------ -``praw.ini`` uses the `INI file format -`_, which can contain multiple groups -of settings separated into sections. PRAW and Async PRAW refers to each section -as a ``site``. The default site, ``DEFAULT``, is provided in the package's -``praw.ini`` file. This site defines the default settings for interaction with +``praw.ini`` uses the `INI file format `_, which +can contain multiple groups of settings separated into sections. PRAW and Async PRAW +refers to each section as a ``site``. The default site, ``DEFAULT``, is provided in the +package's ``praw.ini`` file. This site defines the default settings for interaction with Reddit. The contents of the package's ``praw.ini`` file are: .. literalinclude:: ../../../asyncpraw/praw.ini - :language: ini + :language: ini + +.. warning:: -.. warning:: Avoid modifying the package's ``praw.ini`` file. Prefer instead to - override its values in your own ``praw.ini`` file. You can even - override settings of the ``DEFAULT`` site in user defined - ``praw.ini`` files. + Avoid modifying the package's ``praw.ini`` file. Prefer instead to override its + values in your own ``praw.ini`` file. You can even override settings of the + ``DEFAULT`` site in user defined ``praw.ini`` files. Defining Additional Sites ------------------------- -In addition to the ``DEFAULT`` site, additional sites can be configured in user -defined ``praw.ini`` files. All sites inherit settings from the ``DEFAULT`` -site and can override whichever settings desired. +In addition to the ``DEFAULT`` site, additional sites can be configured in user defined +``praw.ini`` files. All sites inherit settings from the ``DEFAULT`` site and can +override whichever settings desired. Defining additional sites is a convenient way to store :ref:`OAuth credentials -` for various accounts, or distinct OAuth applications. For -example, if you have three separate bots, you might create a site for each: +` for various accounts, or distinct OAuth applications. For example, if +you have three separate bots, you might create a site for each: .. _custom_site_example: + .. code-block:: ini - [bot1] - client_id=Y4PJOclpDQy3xZ - client_secret=UkGLTe6oqsMk5nHCJTHLrwgvHpr - password=pni9ubeht4wd50gk - username=fakebot1 + [bot1] + client_id=Y4PJOclpDQy3xZ + client_secret=UkGLTe6oqsMk5nHCJTHLrwgvHpr + password=pni9ubeht4wd50gk + username=fakebot1 - [bot2] - client_id=6abrJJdcIqbclb - client_secret=Kcn6Bj8CClyu4FjVO77MYlTynfj - password=mi1ky2qzpiq8s59j - username=fakebot2 + [bot2] + client_id=6abrJJdcIqbclb + client_secret=Kcn6Bj8CClyu4FjVO77MYlTynfj + password=mi1ky2qzpiq8s59j + username=fakebot2 - [bot3] - client_id=SI8pN3DSbt0zor - client_secret=xaxkj7HNh8kwg8e5t4m6KvSrbTI - password=1guiwevlfo00esyy - username=fakebot3 + [bot3] + client_id=SI8pN3DSbt0zor + client_secret=xaxkj7HNh8kwg8e5t4m6KvSrbTI + password=1guiwevlfo00esyy + username=fakebot3 Choosing a Site --------------- -Site selection is done via the ``site_name`` parameter to :class:`.Reddit`. For -example, to use the settings defined for ``bot2`` as shown above, initialize -:class:`.Reddit` like so: +Site selection is done via the ``site_name`` parameter to :class:`.Reddit`. For example, +to use the settings defined for ``bot2`` as shown above, initialize :class:`.Reddit` +like so: .. code-block:: python - reddit = asyncpraw.Reddit("bot2", user_agent="bot2 user agent") + reddit = asyncpraw.Reddit("bot2", user_agent="bot2 user agent") -.. note:: In the above example you can obviate passing ``user_agent`` if you - add the setting ``user_agent=...`` in the ``[bot2]`` site definition. +.. note:: -A site can also be selected via a ``praw_site`` environment variable. This -approach has precedence over the ``site_name`` parameter described above. + In the above example you can obviate passing ``user_agent`` if you add the setting + ``user_agent=...`` in the ``[bot2]`` site definition. + +A site can also be selected via a ``praw_site`` environment variable. This approach has +precedence over the ``site_name`` parameter described above. Using Interpolation ------------------- -By default Async PRAW doesn't apply any interpolation on the config file but this can -be changed with the ``config_interpolation`` parameter which can be set to -"basic" or "extended". +By default Async PRAW doesn't apply any interpolation on the config file but this can be +changed with the ``config_interpolation`` parameter which can be set to "basic" or +"extended". -This can be useful to separate the components of the ``user_agent`` into -individual variables, for example: +This can be useful to separate the components of the ``user_agent`` into individual +variables, for example: .. _interpolation_site_example: + .. code-block:: ini - [bot1] - bot_name=MyBot - bot_version=1.2.3 - bot_author=MyUser - user_agent=script:%(bot_name)s:v%(bot_version)s (by u/%(bot_author)s) + [bot1] + bot_name=MyBot + bot_version=1.2.3 + bot_author=MyUser + user_agent=script:%(bot_name)s:v%(bot_version)s (by u/%(bot_author)s) -This uses basic interpolation thus :class:`.Reddit` need to be initialized as -follows: +This uses basic interpolation thus :class:`.Reddit` need to be initialized as follows: .. code-block:: python - reddit = asyncpraw.Reddit("bot1", config_interpolation="basic") + reddit = asyncpraw.Reddit("bot1", config_interpolation="basic") -Then the value of ``reddit.config.user_agent`` will be -``script:MyBot:v1.2.3 (by /u/MyUser)``. +Then the value of ``reddit.config.user_agent`` will be ``script:MyBot:v1.2.3 (by +/u/MyUser)``. See `Interpolation of values -`_ -for details. +`_ for +details. + +.. warning:: -.. warning:: The ConfigParser instance is cached internally at the class level, - it is shared across all instances of :class:`.Reddit` and once set - it's not overridden by future invocations. + The ConfigParser instance is cached internally at the class level, it is shared + across all instances of :class:`.Reddit` and once set it's not overridden by future + invocations. diff --git a/docs/getting_started/configuration/reddit_initialization.rst b/docs/getting_started/configuration/reddit_initialization.rst index 64b72be2d..f1abc62f8 100644 --- a/docs/getting_started/configuration/reddit_initialization.rst +++ b/docs/getting_started/configuration/reddit_initialization.rst @@ -3,19 +3,20 @@ Keyword Arguments to :class:`.Reddit` ===================================== -Most of Async PRAW's documentation will demonstrate configuring Async PRAW -through the use of keyword arguments when initializing instances of -:class:`.Reddit`. All of the :ref:`configuration_options` can be specified -using a keyword argument of the same name. +Most of Async PRAW's documentation will demonstrate configuring Async PRAW through the +use of keyword arguments when initializing instances of :class:`.Reddit`. All of the +:ref:`configuration_options` can be specified using a keyword argument of the same name. -For example, if we wanted to explicitly pass the information for ``bot3`` -defined in :ref:`the praw.ini custom site example ` -without using the ``bot3`` site, we would initialize :class:`.Reddit` as: +For example, if we wanted to explicitly pass the information for ``bot3`` defined in +:ref:`the praw.ini custom site example ` without using the ``bot3`` +site, we would initialize :class:`.Reddit` as: .. code-block:: python - reddit = asyncpraw.Reddit(client_id="SI8pN3DSbt0zor", - client_secret="xaxkj7HNh8kwg8e5t4m6KvSrbTI", - password="1guiwevlfo00esyy", - user_agent="testscript by u/fakebot3", - username="fakebot3") + reddit = asyncpraw.Reddit( + client_id="SI8pN3DSbt0zor", + client_secret="xaxkj7HNh8kwg8e5t4m6KvSrbTI", + password="1guiwevlfo00esyy", + user_agent="testscript by u/fakebot3", + username="fakebot3", + ) diff --git a/docs/getting_started/faq.rst b/docs/getting_started/faq.rst index bc3a46446..689b9c398 100644 --- a/docs/getting_started/faq.rst +++ b/docs/getting_started/faq.rst @@ -7,7 +7,7 @@ Q: How can I refresh a comment/subreddit/submission? A: There is two ways to do this: -* Directly calling the constructors will refresh the value: +- Directly calling the constructors will refresh the value: .. code-block:: python @@ -15,7 +15,7 @@ A: There is two ways to do this: await reddit.subreddit(display_name=subreddit.display_name) await reddit.submission(id=submission.id) -* Calling :meth:`~.RedditBase.load`: +- Calling :meth:`~.RedditBase.load`: .. code-block:: python @@ -25,23 +25,22 @@ A: There is two ways to do this: .. _faq2: -Q: Whenever I try to do anything, I get an ``invalid_grant`` error. What is the -cause? +Q: Whenever I try to do anything, I get an ``invalid_grant`` error. What is the cause? -A: This means that either you provided the wrong password and/or the account -you are trying to sign in with has 2FA enabled, and as such, either needs a 2FA -token or a refresh token to sign in. A refresh token is preferred, because then -you will not need to enter a 2FA token in order to sign in, and the session -will last for longer than an hour. Refer to :ref:`2FA` and :ref:`refresh_token` -in order to use the respective auth methods. +A: This means that either you provided the wrong password and/or the account you are +trying to sign in with has 2FA enabled, and as such, either needs a 2FA token or a +refresh token to sign in. A refresh token is preferred, because then you will not need +to enter a 2FA token in order to sign in, and the session will last for longer than an +hour. Refer to :ref:`2FA` and :ref:`refresh_token` in order to use the respective auth +methods. .. _faq3: -Q: Some options (like getting moderator logs from r/mod) keep on timing out. -How can I extend the timeout? +Q: Some options (like getting moderator logs from r/mod) keep on timing out. How can I +extend the timeout? -A: Set the timeout config option or initialize :class:`.Reddit` with a timeout -of your choosing. +A: Set the timeout config option or initialize :class:`.Reddit` with a timeout of your +choosing. .. _faq4: @@ -62,17 +61,18 @@ see the available authentication methods. Q: Help, searching for URLs keeps on redirecting me to ``/submit``! -Q2: I keep on getting this exception: ``asyncprawcore.exceptions.Redirect: Redirect to /submit`` +Q2: I keep on getting this exception: ``asyncprawcore.exceptions.Redirect: Redirect to +/submit`` -A: Reddit redirects URL searches to the submit page of the URL. To search for -the URL, prefix ``url:`` to the url and surround the url in quotation marks. +A: Reddit redirects URL searches to the submit page of the URL. To search for the URL, +prefix ``url:`` to the url and surround the url in quotation marks. For example, the code block: .. code-block:: python - subreddit = await reddit.subreddit('all') - async for result in subreddit.search('https://google.com'): + subreddit = await reddit.subreddit("all") + async for result in subreddit.search("https://google.com"): # do things with results ... @@ -80,7 +80,7 @@ Will become this code block: .. code-block:: python - subreddit = await reddit.subreddit('all') + subreddit = await reddit.subreddit("all") async for result in subreddit.search('url:"https://google.com"'): # do things with results ... diff --git a/docs/getting_started/installation.rst b/docs/getting_started/installation.rst index 9de8d8eb1..a61f4448e 100644 --- a/docs/getting_started/installation.rst +++ b/docs/getting_started/installation.rst @@ -1,21 +1,24 @@ Installing Async PRAW ===================== -Async PRAW supports Python 3.6+. The recommended way to install Async PRAW is via ``pip``. +Async PRAW supports Python 3.6+. The recommended way to install Async PRAW is via +``pip``. .. code-block:: bash - pip install asyncpraw + pip install asyncpraw -.. note:: Depending on your system, you may need to use ``pip3`` to install - packages for Python 3. +.. note:: -.. warning:: Avoid using ``sudo`` to install packages. Do you `really` trust - this package? + Depending on your system, you may need to use ``pip3`` to install packages for + Python 3. -For instructions on installing Python and pip see "The Hitchhiker's Guide to -Python" `Installation Guides -`_. +.. warning:: + + Avoid using ``sudo`` to install packages. Do you `really` trust this package? + +For instructions on installing Python and pip see "The Hitchhiker's Guide to Python" +`Installation Guides `_. Updating Async PRAW ------------------- @@ -24,30 +27,30 @@ Async PRAW can be updated by running: .. code-block:: bash - pip install --upgrade asyncpraw + pip install --upgrade asyncpraw Installing Older Versions ------------------------- -Older versions of Async PRAW can be installed by specifying the version number as -part of the installation command: +Older versions of Async PRAW can be installed by specifying the version number as part +of the installation command: .. code-block:: bash - pip install asyncpraw==7.1.0 + pip install asyncpraw==7.1.0 Installing the Latest Development Version ----------------------------------------- -Is there a feature that was recently merged into Async PRAW that you cannot wait to -take advantage of? If so, you can install Async PRAW directly from GitHub like so: +Is there a feature that was recently merged into Async PRAW that you cannot wait to take +advantage of? If so, you can install Async PRAW directly from GitHub like so: .. code-block:: bash - pip install --upgrade https://github.com/praw-dev/asyncpraw/archive/master.zip + pip install --upgrade https://github.com/praw-dev/asyncpraw/archive/master.zip You can also directly clone a copy of the repository using git, like so: .. code-block:: bash - pip install --upgrade git+https://github.com/praw-dev/asyncpraw.git + pip install --upgrade git+https://github.com/praw-dev/asyncpraw.git diff --git a/docs/getting_started/logging.rst b/docs/getting_started/logging.rst index 915bbed41..c4a723397 100644 --- a/docs/getting_started/logging.rst +++ b/docs/getting_started/logging.rst @@ -1,38 +1,37 @@ Logging in Async PRAW ===================== -It is occasionally useful to observe the HTTP requests that Async PRAW is issuing. To -do so you have to configure and enable logging. +It is occasionally useful to observe the HTTP requests that Async PRAW is issuing. To do +so you have to configure and enable logging. Add the following to your code to log everything available: .. code-block:: python - import logging + import logging - handler = logging.StreamHandler() - handler.setLevel(logging.DEBUG) - for logger_name in ("asyncpraw", "asyncprawcore"): - logger = logging.getLogger(logger_name) - logger.setLevel(logging.DEBUG) - logger.addHandler(handler) + handler = logging.StreamHandler() + handler.setLevel(logging.DEBUG) + for logger_name in ("asyncpraw", "asyncprawcore"): + logger = logging.getLogger(logger_name) + logger.setLevel(logging.DEBUG) + logger.addHandler(handler) - -When properly configured, HTTP requests that are issued should produce output -similar to the following: +When properly configured, HTTP requests that are issued should produce output similar to +the following: .. code-block:: text - Fetching: GET https://oauth.reddit.com/api/v1/me - Data: None - Params: {'raw_json': 1} - Response: 200 (876 bytes) + Fetching: GET https://oauth.reddit.com/api/v1/me + Data: None + Params: {'raw_json': 1} + Response: 200 (876 bytes) -Furthermore, any API ratelimits from POST actions that are handled will produce -a log entry with a message similar to the following message: +Furthermore, any API ratelimits from POST actions that are handled will produce a log +entry with a message similar to the following message: .. code-block:: text - Rate limit hit, sleeping for 5.5 seconds + Rate limit hit, sleeping for 5.5 seconds For more information on logging, see :py:class:`logging.Logger`. diff --git a/docs/getting_started/multiple_instances.rst b/docs/getting_started/multiple_instances.rst index abfaf5620..98d8e9c35 100644 --- a/docs/getting_started/multiple_instances.rst +++ b/docs/getting_started/multiple_instances.rst @@ -1,24 +1,25 @@ Running Multiple Instances of Async PRAW ======================================== -Async PRAW performs rate limiting dynamically based on the HTTP -response headers from Reddit. As a result you can safely run a handful of -Async PRAW instances without any additional configuration. +Async PRAW performs rate limiting dynamically based on the HTTP response headers from +Reddit. As a result you can safely run a handful of Async PRAW instances without any +additional configuration. -.. note:: Running more than a dozen or so instances of Async PRAW concurrently - may occasionally result in exceeding Reddit's rate limits as each - instance can only guess how many other instances are running. +.. note:: -If you are authorized on other users' behalf, each authorization should have -its own rate limit, even when running from a single IP address. + Running more than a dozen or so instances of Async PRAW concurrently may + occasionally result in exceeding Reddit's rate limits as each instance can only + guess how many other instances are running. + +If you are authorized on other users' behalf, each authorization should have its own +rate limit, even when running from a single IP address. Multiple Programs ----------------- -The recommended way to run multiple instances of Async PRAW is to simply write -separate independent Python programs. With this approach one program can -monitor a comment stream and reply as needed, and another program can monitor a -submission stream, for example. +The recommended way to run multiple instances of Async PRAW is to simply write separate +independent Python programs. With this approach one program can monitor a comment stream +and reply as needed, and another program can monitor a submission stream, for example. -If these programs need to share data consider using a third-party system such -as a database or queuing system. +If these programs need to share data consider using a third-party system such as a +database or queuing system. diff --git a/docs/getting_started/quick_start.rst b/docs/getting_started/quick_start.rst index 1efb94204..fcee74a68 100644 --- a/docs/getting_started/quick_start.rst +++ b/docs/getting_started/quick_start.rst @@ -1,52 +1,45 @@ Quick Start =========== -In this section, we go over everything you need to know to start building -scripts or bots using Async PRAW, the Python Reddit API Wrapper. It's fun and -easy. Let's get started. +In this section, we go over everything you need to know to start building scripts or +bots using Async PRAW, the Python Reddit API Wrapper. It's fun and easy. Let's get +started. Prerequisites ------------- :Python Knowledge: You need to know at least a little Python and some understanding - asynchronous usage in python to use Async PRAW; it's an - asynchronous a Python wrapper after all. Async PRAW supports - `Python 3.6+`_. If you are stuck on a problem, `r/learnpython`_ - is a great place to ask for help. - -:Reddit Knowledge: A basic understanding of how Reddit works is a - must. In the event you are not already familiar with Reddit - start at `Reddit Help`_. - -:Reddit Account: A Reddit account is required to access Reddit's API. Create - one at `reddit.com`_. - -:Client ID & Client Secret: These two values are needed to access Reddit's API - as a **script** application (see :ref:`oauth` for - other application types). If you don't already have - a client ID and client secret, follow Reddit's - `First Steps Guide`_ to create them. - -:User Agent: A user agent is a unique identifier that helps Reddit determine - the source of network requests. To use Reddit's API, you need a - unique and descriptive user agent. The recommended format is - ``:: (by u/)``. For example, - ``android:com.example.myredditapp:v1.2.3 (by u/kemitche)``. Read - more about user agents at `Reddit's API wiki page`_. - - -.. _`Python 3.6+`: https://docs.python.org/3/tutorial/index.html -.. _`r/learnpython`: https://www.reddit.com/r/learnpython/ -.. _reddit.com: https://www.reddit.com -.. _`Reddit Help`: https://www.reddithelp.com/en -.. _`Reddit's API wiki page`: https://github.com/reddit/reddit/wiki/API + asynchronous usage in python to use Async PRAW; it's an asynchronous a Python + wrapper after all. Async PRAW supports `Python 3.6+`_. If you are stuck on a + problem, `r/learnpython`_ is a great place to ask for help. +:Reddit Knowledge: A basic understanding of how Reddit works is a must. In the event you + are not already familiar with Reddit start at `Reddit Help`_. +:Reddit Account: A Reddit account is required to access Reddit's API. Create one at + reddit.com_. +:Client ID & Client Secret: These two values are needed to access Reddit's API as a + **script** application (see :ref:`oauth` for other application types). If you don't + already have a client ID and client secret, follow Reddit's `First Steps Guide`_ to + create them. +:User Agent: A user agent is a unique identifier that helps Reddit determine the source + of network requests. To use Reddit's API, you need a unique and descriptive user + agent. The recommended format is ``:: (by + u/)``. For example, ``android:com.example.myredditapp:v1.2.3 (by + u/kemitche)``. Read more about user agents at `Reddit's API wiki page`_. + +.. _first steps guide: https://github.com/reddit/reddit/wiki/OAuth2-Quick-Start-Example#first-steps + +.. _python 3.6+: https://docs.python.org/3/tutorial/index.html + +.. _r/learnpython: https://www.reddit.com/r/learnpython/ -.. _`First Steps Guide`: - https://github.com/reddit/reddit/wiki/OAuth2-Quick-Start-Example#first-steps +.. _reddit help: https://www.reddithelp.com/en + +.. _reddit's api wiki page: https://github.com/reddit/reddit/wiki/API + +.. _reddit.com: https://www.reddit.com -With these prerequisites satisfied, you are ready to learn how to do some of -the most common tasks with Reddit's API. +With these prerequisites satisfied, you are ready to learn how to do some of the most +common tasks with Reddit's API. Common Tasks ------------ @@ -54,117 +47,122 @@ Common Tasks Obtain a :class:`.Reddit` Instance ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.. warning:: For the sake of brevity, the following examples pass authentication - information via arguments to :py:func:`asyncpraw.Reddit`. If you do - this, you need to be careful not to reveal this information to the - outside world if you share your code. It is recommended to use a - :ref:`praw.ini file ` in order to keep your - authentication information separate from your code. +.. warning:: -You need an instance of the :class:`.Reddit` class to do *anything* with -Async PRAW. There are two distinct states a :class:`.Reddit` instance can be in: -:ref:`read-only `, and :ref:`authorized `. + For the sake of brevity, the following examples pass authentication information via + arguments to :py:func:`asyncpraw.Reddit`. If you do this, you need to be careful not + to reveal this information to the outside world if you share your code. It is + recommended to use a :ref:`praw.ini file ` in order to keep your + authentication information separate from your code. + +You need an instance of the :class:`.Reddit` class to do *anything* with Async PRAW. +There are two distinct states a :class:`.Reddit` instance can be in: :ref:`read-only +`, and :ref:`authorized `. .. _read-only: Read-only :class:`.Reddit` Instances -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +++++++++++++++++++++++++++++++++++++ -To create a read-only :class:`.Reddit` instance, you need three pieces of -information: +To create a read-only :class:`.Reddit` instance, you need three pieces of information: -1) Client ID -2) Client secret -3) User agent +1. Client ID +2. Client secret +3. User agent -You may choose to provide these by passing in three keyword arguments when -calling the initializer of the :class:`.Reddit` class: ``client_id``, -``client_secret``, ``user_agent`` (see :ref:`configuration` for other methods -of providing this information). For example: +You may choose to provide these by passing in three keyword arguments when calling the +initializer of the :class:`.Reddit` class: ``client_id``, ``client_secret``, +``user_agent`` (see :ref:`configuration` for other methods of providing this +information). For example: .. code-block:: python import asyncpraw - reddit = asyncpraw.Reddit(client_id="my client id", - client_secret="my client secret", - user_agent="my user agent") + reddit = asyncpraw.Reddit( + client_id="my client id", + client_secret="my client secret", + user_agent="my user agent", + ) -Just like that, you now have a read-only :class:`.Reddit` instance. +Just like that, you now have a read-only :class:`.Reddit` instance. .. code-block:: python print(reddit.read_only) # Output: True -With a read-only instance, you can do something like obtaining 10 "hot" -submissions from ``r/learnpython``: +With a read-only instance, you can do something like obtaining 10 "hot" submissions from +``r/learnpython``: .. code-block:: python # continued from code above - subreddit = await reddit.subreddit("learnpython") + subreddit = await reddit.subreddit("learnpython") async for submission in subreddit.hot(limit=10): print(submission.title) # Output: 10 submissions -If you want to do more than retrieve public information from Reddit, then you -need an authorized :class:`.Reddit` instance. +If you want to do more than retrieve public information from Reddit, then you need an +authorized :class:`.Reddit` instance. + +.. note:: -.. note:: In the above example we are limiting the results to 10. Without the - ``limit`` parameter Async PRAW should yield as many results as it can with - a single request. For most endpoints this results in 100 items per - request. If you want to retrieve as many as possible pass in - ``limit=None``. + In the above example we are limiting the results to 10. Without the ``limit`` + parameter Async PRAW should yield as many results as it can with a single request. + For most endpoints this results in 100 items per request. If you want to retrieve as + many as possible pass in ``limit=None``. .. _authorized: Authorized :class:`.Reddit` Instances -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ++++++++++++++++++++++++++++++++++++++ -In order to create an authorized :class:`.Reddit` instance, two additional -pieces of information are required for **script** applications (see -:ref:`oauth` for other application types): +In order to create an authorized :class:`.Reddit` instance, two additional pieces of +information are required for **script** applications (see :ref:`oauth` for other +application types): -4) Your Reddit username, and -5) Your Reddit password +4. Your Reddit username, and +5. Your Reddit password -Again, you may choose to provide these by passing in keyword arguments -``username`` and ``password`` when you call the :class:`.Reddit` initializer, -like the following: +Again, you may choose to provide these by passing in keyword arguments ``username`` and +``password`` when you call the :class:`.Reddit` initializer, like the following: .. code-block:: python import asyncpraw - reddit = asyncpraw.Reddit(client_id="my client id", - client_secret="my client secret", - user_agent="my user agent", - username="my username", - password="my password") + reddit = asyncpraw.Reddit( + client_id="my client id", + client_secret="my client secret", + user_agent="my user agent", + username="my username", + password="my password", + ) print(reddit.read_only) # Output: False -Now you can do whatever your Reddit account is authorized to do. And you can -switch back to read-only mode whenever you want: +Now you can do whatever your Reddit account is authorized to do. And you can switch back +to read-only mode whenever you want: .. code-block:: python # continued from code above reddit.read_only = True -.. note:: If you are uncomfortable hard-coding your credentials into your - program, there are some options available to you. Please see: - :ref:`configuration`. +.. note:: + + If you are uncomfortable hard-coding your credentials into your program, there are + some options available to you. Please see: :ref:`configuration`. Obtain a :class:`.Subreddit` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -To obtain a :class:`.Subreddit` instance, pass the subreddit's name when -calling ``subreddit`` on your :class:`.Reddit` instance. For example: +To obtain a :class:`.Subreddit` instance, pass the subreddit's name when calling +``subreddit`` on your :class:`.Reddit` instance. For example: .. code-block:: python @@ -181,9 +179,9 @@ calling ``subreddit`` on your :class:`.Reddit` instance. For example: Obtain :class:`.Submission` Instances from a :class:`.Subreddit` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Now that you have a :class:`.Subreddit` instance, you can iterate through some -of its submissions, each bound to an instance of :class:`.Submission`. There -are several sorts that you can iterate through: +Now that you have a :class:`.Subreddit` instance, you can iterate through some of its +submissions, each bound to an instance of :class:`.Submission`. There are several sorts +that you can iterate through: - controversial - gilded @@ -194,9 +192,9 @@ are several sorts that you can iterate through: .. _submission-iteration: -Each of these methods will immediately return a :class:`.ListingGenerator`, -which is to be iterated through. For example, to iterate through the first 10 -submissions based on the ``hot`` sort for a given subreddit try: +Each of these methods will immediately return a :class:`.ListingGenerator`, which is to +be iterated through. For example, to iterate through the first 10 submissions based on +the ``hot`` sort for a given subreddit try: .. code-block:: python @@ -211,9 +209,11 @@ submissions based on the ``hot`` sort for a given subreddit try: print(submission.url) # Output: the URL the submission points to or the submission's URL if it's a self post -.. note:: The act of calling a method that returns a :class:`.ListingGenerator` - does not result in any network requests until you begin to iterate - through the :class:`.ListingGenerator`. +.. note:: + + The act of calling a method that returns a :class:`.ListingGenerator` does not + result in any network requests until you begin to iterate through the + :class:`.ListingGenerator`. You can create :class:`.Submission` instances in other ways too: @@ -225,17 +225,15 @@ You can create :class:`.Submission` instances in other ways too: # Output: reddit will soon only be available ... # or - submission =await reddit.submission(url='https://www.reddit.com/...') - + submission = await reddit.submission(url="https://www.reddit.com/...") Obtain :class:`.Redditor` Instances ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -There are several ways to obtain a redditor (a :class:`.Redditor` instance). -Two of the most common ones are: +There are several ways to obtain a redditor (a :class:`.Redditor` instance). Two of the +most common ones are: -- via the ``author`` attribute of a :class:`.Submission` or :class:`.Comment` - instance +- via the ``author`` attribute of a :class:`.Submission` or :class:`.Comment` instance - via the :meth:`.redditor` method of :class:`.Reddit` For example: @@ -255,11 +253,11 @@ For example: Obtain :class:`.Comment` Instances ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Submissions have a ``comments`` attribute that is a :class:`.CommentForest` -instance. That instance is iterable and represents the top-level comments of -the submission by the default comment sort (``confidence``). If you instead -want to iterate over *all* comments as a flattened list you can call the -:meth:`.list` method on a :class:`.CommentForest` instance. For example: +Submissions have a ``comments`` attribute that is a :class:`.CommentForest` instance. +That instance is iterable and represents the top-level comments of the submission by the +default comment sort (``confidence``). If you instead want to iterate over *all* +comments as a flattened list you can call the :meth:`.list` method on a +:class:`.CommentForest` instance. For example: .. code-block:: python @@ -267,25 +265,26 @@ want to iterate over *all* comments as a flattened list you can call the top_level_comments = await submission.comments() all_comments = await submission.comments.list() -.. note:: The comment sort order can be changed by updating the value of - ``comment_sort`` on the :class:`.Submission` instance prior to - accessing ``comments`` (see: `/api/set_suggested_sort - `_ for - possible values). For example, to have comments sorted by ``new`` try - something like: +.. note:: + + The comment sort order can be changed by updating the value of ``comment_sort`` on + the :class:`.Submission` instance prior to accessing ``comments`` (see: + `/api/set_suggested_sort + `_ for possible values). + For example, to have comments sorted by ``new`` try something like: - .. code-block:: python + .. code-block:: python - # assume you have a Reddit instance bound to variable `reddit` - submission = await reddit.submission(id="39zje0") - submission.comment_sort = "new" - top_level_comments = await submission.comments() + # assume you have a Reddit instance bound to variable `reddit` + submission = await reddit.submission(id="39zje0") + submission.comment_sort = "new" + top_level_comments = await submission.comments() As you may be aware there will periodically be :class:`.MoreComments` instances -scattered throughout the forest. Replace those :class:`.MoreComments` instances -at any time by calling :meth:`.replace_more` on a :class:`.CommentForest` -instance. Calling :meth:`.replace_more` access ``comments``, and so must be done -after ``comment_sort`` is updated. See :ref:`extracting_comments` for an example. +scattered throughout the forest. Replace those :class:`.MoreComments` instances at any +time by calling :meth:`.replace_more` on a :class:`.CommentForest` instance. Calling +:meth:`.replace_more` access ``comments``, and so must be done after ``comment_sort`` is +updated. See :ref:`extracting_comments` for an example. .. _determine-available-attributes-of-an-object: @@ -293,9 +292,9 @@ Determine Available Attributes of an Object ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ If you have a Async PRAW object, e.g., :class:`.Comment`, :class:`.Message`, -:class:`.Redditor`, or :class:`.Submission`, and you want to see what -attributes are available along with their values, use the built-in -:py:func:`vars` function of python. For example: +:class:`.Redditor`, or :class:`.Submission`, and you want to see what attributes are +available along with their values, use the built-in :py:func:`vars` function of python. +For example: .. code-block:: python diff --git a/docs/index.rst b/docs/index.rst index 4a5bb04eb..a2853159d 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -3,63 +3,67 @@ Async PRAW: The Asynchronous Python Reddit API Wrapper Async PRAW's documentation is organized into the following sections: -* :ref:`getting_started` -* :ref:`code_overview` -* :ref:`tutorial` -* :ref:`package_info` +- :ref:`getting_started` +- :ref:`code_overview` +- :ref:`tutorial` +- :ref:`package_info` Documentation Conventions ------------------------- -Unless otherwise mentioned, all examples in this document assume the use of a -**script** application. See :ref:`oauth` for information on using **installed** -applications and **web** applications. +Unless otherwise mentioned, all examples in this document assume the use of a **script** +application. See :ref:`oauth` for information on using **installed** applications and +**web** applications. .. _getting_started: + .. toctree:: - :maxdepth: 1 - :caption: Getting Started + :maxdepth: 1 + :caption: Getting Started - getting_started/quick_start - getting_started/installation - getting_started/authentication - getting_started/configuration - getting_started/multiple_instances - getting_started/logging - getting_started/faq + getting_started/quick_start + getting_started/installation + getting_started/authentication + getting_started/configuration + getting_started/multiple_instances + getting_started/logging + getting_started/faq .. _code_overview: + .. toctree:: - :maxdepth: 1 - :caption: Code Overview + :maxdepth: 1 + :caption: Code Overview - code_overview/reddit_instance - code_overview/asyncpraw_models - code_overview/exceptions - code_overview/other + code_overview/reddit_instance + code_overview/asyncpraw_models + code_overview/exceptions + code_overview/other .. _tutorial: + .. toctree:: - :maxdepth: 1 - :caption: Tutorials + :maxdepth: 1 + :caption: Tutorials - tutorials/comments.rst - tutorials/refresh_token.rst - tutorials/reply_bot.rst + tutorials/comments.rst + tutorials/refresh_token.rst + tutorials/reply_bot.rst .. _package_info: + .. toctree:: - :maxdepth: 1 - :caption: Package Info + :maxdepth: 1 + :caption: Package Info - package_info/change_log - package_info/contributing - package_info/glossary - package_info/asyncpraw_migration - package_info/praw7_migration - package_info/references + package_info/change_log + package_info/contributing + package_info/glossary + package_info/asyncpraw_migration + package_info/praw7_migration + package_info/references .. toctree:: - :hidden: + :hidden: - genindex + genindex diff --git a/docs/package_info/asyncpraw_migration.rst b/docs/package_info/asyncpraw_migration.rst index f356f95d6..42b370b84 100644 --- a/docs/package_info/asyncpraw_migration.rst +++ b/docs/package_info/asyncpraw_migration.rst @@ -9,11 +9,12 @@ Network Requests .. _network_requests: -Async PRAW utilizes `aiohttp `_ to make network requests to Reddit's API. Since aiohttp can -only be used in an asynchronous environment, all network requests need to be awaited. Due to this, most Async PRAW -methods need to be awaited as well. You can tell if a method needs awaited by looking at the docs. For example, -:meth:`.me` has the word ``await`` before ``me(use_cache: bool = True)`` in the header for that method -since that method makes a network request. +Async PRAW utilizes `aiohttp `_ to make network requests to +Reddit's API. Since aiohttp can only be used in an asynchronous environment, all network +requests need to be awaited. Due to this, most Async PRAW methods need to be awaited as +well. You can tell if a method needs awaited by looking at the docs. For example, +:meth:`.me` has the word ``await`` before ``me(use_cache: bool = True)`` in the header +for that method since that method makes a network request. Lazy Loading ------------ @@ -66,26 +67,27 @@ want to remove a post, you don't need the object fully fetched to do that. The following objects are still lazily loaded by default: -* :class:`.Subreddit` -* :class:`.Redditor` -* :class:`.LiveThread` -* :class:`.Multireddit` +- :class:`.Subreddit` +- :class:`.Redditor` +- :class:`.LiveThread` +- :class:`.Multireddit` You can pass ``fetch=True`` in their respective helper method to fully load it. Inversely, the following objects are now fully fetched when initialized: -* :class:`.Submission` -* :class:`.Comment` -* :class:`.WikiPage` -* :class:`.RemovalReason` -* :class:`.Collection` -* :class:`.Emoji` -* :class:`.LiveUpdate` -* :class:`.Rule` -* :class:`.Preferences` +- :class:`.Submission` +- :class:`.Comment` +- :class:`.WikiPage` +- :class:`.RemovalReason` +- :class:`.Collection` +- :class:`.Emoji` +- :class:`.LiveUpdate` +- :class:`.Rule` +- :class:`.Preferences` -You can pass ``lazy=True`` in their respective helper method if you want to lazily load it. +You can pass ``lazy=True`` in their respective helper method if you want to lazily load +it. In addition, there will be a ``load()`` method provided for manually fetching/refreshing objects that subclass :class:`.RedditBase`. If you need to later on access an attribute @@ -133,4 +135,4 @@ method. Also, they are not lazily loaded by default anymore. print(page.content_md) # using slices - rule = await subreddit.mod.rules.get_rule(slice(-3, None)) # to get the last 3 rules \ No newline at end of file + rule = await subreddit.mod.rules.get_rule(slice(-3, None)) # to get the last 3 rules diff --git a/docs/package_info/contributing.rst b/docs/package_info/contributing.rst index 05ce98cba..a4f8baa2a 100644 --- a/docs/package_info/contributing.rst +++ b/docs/package_info/contributing.rst @@ -1,54 +1,56 @@ Contributing to Async PRAW ========================== -Async PRAW gladly welcomes new contributions. As with most larger projects, we have -an established consistent way of doing things. A consistent style increases -readability, decreases bug-potential and makes it faster to understand how -everything works together. +Async PRAW gladly welcomes new contributions. As with most larger projects, we have an +established consistent way of doing things. A consistent style increases readability, +decreases bug-potential and makes it faster to understand how everything works together. Async PRAW follows :PEP:`8` and :PEP:`257`. The ``pre_push.py`` script can be used to -test for compliance with these PEPs in addition to providing a few other -checks. The following are Async PRAW-specific guidelines in addition to those PEP's. +test for compliance with these PEPs in addition to providing a few other checks. The +following are Async PRAW-specific guidelines in addition to those PEP's. -.. note:: Python 3.6+ is needed to run the script. +.. note:: + + Python 3.6+ is needed to run the script. -.. note:: In order to install the dependencies needed to run the script, you can - install the ``[dev]`` package of asyncpraw, like so: +.. note:: - .. code-block:: bash + In order to install the dependencies needed to run the script, you can install the + ``[dev]`` package of asyncpraw, like so: - pip install asyncpraw[dev] + .. code-block:: bash + + pip install asyncpraw[dev] Code ---- -* Within a single file classes are sorted alphabetically where inheritance - permits. -* Within a class, methods are sorted alphabetically within their respective - groups with the following as the grouping order: +- Within a single file classes are sorted alphabetically where inheritance permits. +- Within a class, methods are sorted alphabetically within their respective groups with + the following as the grouping order: - * Static methods - * Class methods - * Properties - * Instance Methods + - Static methods + - Class methods + - Properties + - Instance Methods -* Use descriptive names for the catch-all keyword argument. E.g., - ``**other_options`` rather than ``**kwargs``. +- Use descriptive names for the catch-all keyword argument. E.g., ``**other_options`` + rather than ``**kwargs``. Testing ------- Contributions to Async PRAW requires 100% test coverage as reported by `Coveralls -`_. If you know how to add a -feature, but aren't sure how to write the necessary tests, please open a PR -anyway so we can work with you to write the necessary tests. +`_. If you know how to add a feature, +but aren't sure how to write the necessary tests, please open a PR anyway so we can work +with you to write the necessary tests. Running the Test Suite ~~~~~~~~~~~~~~~~~~~~~~ -`Github Actions `_ automatically runs -all updates to known branches and pull requests. However, it's useful to be -able to run the tests locally. The simplest way is via: +`Github Actions `_ automatically runs all +updates to known branches and pull requests. However, it's useful to be able to run the +tests locally. The simplest way is via: .. code-block:: bash @@ -58,66 +60,64 @@ Without any configuration or modification, all the tests should pass. .. note:: - Async PRAW uses a fork of `vcrpy` before you can run tests locally you must install the forked version. + Async PRAW uses a fork of `vcrpy` before you can run tests locally you must install + the forked version. .. code-block:: bash pip install https://github.com/LilSpazJoekp/vcrpy/archive/asyncpraw.zip - Adding and Updating Integration Tests ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Async PRAW's integration tests utilize `vcrpy -`_ to record an interaction with -Reddit. The recorded interaction is then replayed for subsequent test runs. +`_ to record an interaction with Reddit. The +recorded interaction is then replayed for subsequent test runs. To safely record a cassette without leaking your account credentials, Async PRAW -utilizes a number of environment variables which are replaced with placeholders -in the cassettes. The environment variables are (listed in bash export format): +utilizes a number of environment variables which are replaced with placeholders in the +cassettes. The environment variables are (listed in bash export format): -.. code:: bash +.. code-block:: bash - export prawtest_client_id=myclientid - export prawtest_client_secret=myclientsecret - export prawtest_password=mypassword - export prawtest_test_subreddit=reddit_api_test - export prawtest_username=myusername - export prawtest_user_agent=praw_pytest + export prawtest_client_id=myclientid + export prawtest_client_secret=myclientsecret + export prawtest_password=mypassword + export prawtest_test_subreddit=reddit_api_test + export prawtest_username=myusername + export prawtest_user_agent=praw_pytest -By setting these environment variables prior to running ``python setup.py -test``, when adding or updating cassettes, instances of ``mypassword`` will be -replaced by the placeholder text ```` and similar for the other -environment variables. +By setting these environment variables prior to running ``python setup.py test``, when +adding or updating cassettes, instances of ``mypassword`` will be replaced by the +placeholder text ```` and similar for the other environment variables. -To use tokens instead of username/password set ``prawtest_refresh_token`` -instead of ``prawtest_password`` and ``prawtest_username``. +To use tokens instead of username/password set ``prawtest_refresh_token`` instead of +``prawtest_password`` and ``prawtest_username``. -When adding or updating a cassette, you will likely want to force requests to -occur again rather than using an existing cassette. The simplest way to rebuild -a cassette is to first delete it, and then rerun the test suite. +When adding or updating a cassette, you will likely want to force requests to occur +again rather than using an existing cassette. The simplest way to rebuild a cassette is +to first delete it, and then rerun the test suite. -Please always verify that only the requests you expect to be made are contained -within your cassette. +Please always verify that only the requests you expect to be made are contained within +your cassette. Documentation ------------- -* All publicly available functions, classes and modules should have a - docstring. -* Use correct terminology. A subreddit's fullname is something like - ``t5_xyfc7``. The correct term for a subreddit's "name" like `python - `_ is its display name. +- All publicly available functions, classes and modules should have a docstring. +- Use correct terminology. A subreddit's fullname is something like ``t5_xyfc7``. The + correct term for a subreddit's "name" like `python `_ + is its display name. Static Checker ~~~~~~~~~~~~~~ -Async PRAW's test suite comes with a checker tool that can warn you of using -incorrect documentation styles (using ``.. code::`` instead of -``.. code-block::``, using ``/r/`` instead of ``r/``, etc.). +Async PRAW's test suite comes with a checker tool that can warn you of using incorrect +documentation styles (using ``.. code::`` instead of ``.. code-block::``, using ``/r/`` +instead of ``r/``, etc.). .. autoclass:: tools.static_word_checks.StaticChecker - :inherited-members: + :inherited-members: Files to Update --------------- @@ -125,18 +125,17 @@ Files to Update AUTHORS.rst ~~~~~~~~~~~ -For your first contribution, please add yourself to the end of the respective -list in the ``AUTHORS.rst`` file. +For your first contribution, please add yourself to the end of the respective list in +the ``AUTHORS.rst`` file. CHANGES.rst ~~~~~~~~~~~ -For feature additions, bugfixes, or code removal please add an appropriate -entry to ``CHANGES.rst``. If the ``Unreleased`` section does not exist at the -top of ``CHANGES.rst`` please add it. See `commit -280525c16ba28cdd69cdbb272a0e2764b1c7e6a0 -`_ -for an example. +For feature additions, bugfixes, or code removal please add an appropriate entry to +``CHANGES.rst``. If the ``Unreleased`` section does not exist at the top of +``CHANGES.rst`` please add it. See `commit 280525c16ba28cdd69cdbb272a0e2764b1c7e6a0 +`_ for +an example. See Also -------- diff --git a/docs/package_info/glossary.rst b/docs/package_info/glossary.rst index 881f5a4e3..f15804d32 100644 --- a/docs/package_info/glossary.rst +++ b/docs/package_info/glossary.rst @@ -3,22 +3,20 @@ Glossary .. _access_token: -* ``Access Token``: A temporary token to allow access to the Reddit API. Lasts - for one hour. +- ``Access Token``: A temporary token to allow access to the Reddit API. Lasts for one + hour. .. _creddit: -* ``Creddit``: Back when the only award was ``Reddit Gold``, a creddit was - equal to one month of Reddit Gold. Creddits have been converted to - ``Reddit Coins``. See :ref:`this ` for more info about the old Reddit - Gold system. +- ``Creddit``: Back when the only award was ``Reddit Gold``, a creddit was equal to one + month of Reddit Gold. Creddits have been converted to ``Reddit Coins``. See :ref:`this + ` for more info about the old Reddit Gold system. .. _fullname: -* ``Fullname``: The fullname of an object is the object's type followed by an - underscore and its base-36 id. An example would be ``t3_1h4f3``, where the - ``t3`` signals that it is a :class:`.Submission`, and the submission ID is - ``1h4f3``. +- ``Fullname``: The fullname of an object is the object's type followed by an underscore + and its base-36 id. An example would be ``t3_1h4f3``, where the ``t3`` signals that it + is a :class:`.Submission`, and the submission ID is ``1h4f3``. Here is a list of the six different types of objects returned from reddit: @@ -44,21 +42,20 @@ Glossary .. _fullname_t6: - - ``t6`` These object represent ``Award``\ s, such as ``Reddit Gold`` or - ``Reddit Silver``. + - ``t6`` These object represent ``Award``\ s, such as ``Reddit Gold`` or ``Reddit + Silver``. .. _gild: -* ``Gild``: Back when the only award was ``Reddit Gold``, gilding a post meant - awarding one month of Reddit Gold. Currently, gilding means awarding one - month of ``Reddit Platinum``, or giving a ``Platinum`` award. +- ``Gild``: Back when the only award was ``Reddit Gold``, gilding a post meant awarding + one month of Reddit Gold. Currently, gilding means awarding one month of ``Reddit + Platinum``, or giving a ``Platinum`` award. .. _websocket: -* ``Websocket``: A special connection type that supports both a client and a - server (the running program and reddit respectively) sending multiple - messages to each other. Reddit uses websockets to notify clients when an - image or video submission is completed, as well as certain types of asset - uploads, such as subreddit banners. If a client does not connect to the - websocket in time, the client will not be notified of the completion of such - uploads. +- ``Websocket``: A special connection type that supports both a client and a server (the + running program and reddit respectively) sending multiple messages to each other. + Reddit uses websockets to notify clients when an image or video submission is + completed, as well as certain types of asset uploads, such as subreddit banners. If a + client does not connect to the websocket in time, the client will not be notified of + the completion of such uploads. diff --git a/docs/package_info/praw7_migration.rst b/docs/package_info/praw7_migration.rst index 07a761820..58653b93a 100644 --- a/docs/package_info/praw7_migration.rst +++ b/docs/package_info/praw7_migration.rst @@ -6,22 +6,20 @@ Exception Handling .. _exception_handling: -Class :class:`.APIException` has also been renamed to -:class:`.RedditAPIException`. Importing :class:`.APIException` will still work, -but is deprecated, but will be removed in Async PRAW 8.0. - -PRAW 7 introduced a fundamental change in how exceptions are received from -Reddit's API. Reddit can return multiple exceptions for one API action, and -as such, the exception :class:`.RedditAPIException` serves as a container for -each of the true exception objects. These objects are instances of -:class:`.RedditErrorItem`, and they contain the information of one "error" from -Reddit's API. They have the three data attributes that :class:`.APIException` -used to contain. - -Most code regarding exceptions can be quickly fixed to work under the new -system. All of the exceptions are stored in the ``items`` attribute of the -exception as entries in a list. In the example code below, observe how -attributes are accessed. +Class :class:`.APIException` has also been renamed to :class:`.RedditAPIException`. +Importing :class:`.APIException` will still work, but is deprecated, but will be removed +in Async PRAW 8.0. + +PRAW 7 introduced a fundamental change in how exceptions are received from Reddit's API. +Reddit can return multiple exceptions for one API action, and as such, the exception +:class:`.RedditAPIException` serves as a container for each of the true exception +objects. These objects are instances of :class:`.RedditErrorItem`, and they contain the +information of one "error" from Reddit's API. They have the three data attributes that +:class:`.APIException` used to contain. + +Most code regarding exceptions can be quickly fixed to work under the new system. All of +the exceptions are stored in the ``items`` attribute of the exception as entries in a +list. In the example code below, observe how attributes are accessed. .. code-block:: python @@ -41,10 +39,10 @@ This can generally be changed to except RedditAPIException as exception: print(exception.items[0].error_type) -However, this should not be done, as this will only work for one error. The -probability of Reddit's API returning multiple exceptions, especially on -submit actions, should be addressed. Rather, iterate over the exception, -and do the action on each item in the iterator. +However, this should not be done, as this will only work for one error. The probability +of Reddit's API returning multiple exceptions, especially on submit actions, should be +addressed. Rather, iterate over the exception, and do the action on each item in the +iterator. .. code-block:: python @@ -55,9 +53,8 @@ and do the action on each item in the iterator. for subexception in exception.items: print(subexception.error_type) -Alternatively, the exceptions are provided to the exception constructor, so -printing the exception directly will also allow you to see all of the -exceptions. +Alternatively, the exceptions are provided to the exception constructor, so printing the +exception directly will also allow you to see all of the exceptions. .. code-block:: python diff --git a/docs/package_info/references.rst b/docs/package_info/references.rst index 919ab47ad..54fd47d1c 100644 --- a/docs/package_info/references.rst +++ b/docs/package_info/references.rst @@ -1,21 +1,18 @@ References ========== -* `Async PRAW Source Code `_. -* `PRAW Source Code `_. -* `Reddit Source Code `_. - This repository has been archived and is no longer updated. -* `Reddit API Wiki Page `_. -* `Reddit API Documentation `_. - -* `Reddit Help `_. Frequently asked questions - and a knowledge base for the site. -* `Reddit Markdown Primer - `_. A guide to the Markdown formatting - used on the site. -* `Reddit Status `_. - Indicates when Reddit is up or down. -* `r/changelog `_. Significant changes to - Reddit's codebase will be announced here in non-developer speak. -* `r/redditdev `_. Ask questions about - Reddit's codebase, Async PRAW, and other API clients here. +- `Async PRAW Source Code `_. +- `PRAW Source Code `_. +- `Reddit Source Code `_. This repository has been + archived and is no longer updated. +- `Reddit API Wiki Page `_. +- `Reddit API Documentation `_. +- `Reddit Help `_. Frequently asked questions and a + knowledge base for the site. +- `Reddit Markdown Primer `_. A guide to the + Markdown formatting used on the site. +- `Reddit Status `_. Indicates when Reddit is up or down. +- `r/changelog `_. Significant changes to Reddit's + codebase will be announced here in non-developer speak. +- `r/redditdev `_. Ask questions about Reddit's + codebase, Async PRAW, and other API clients here. diff --git a/docs/tutorials/comments.rst b/docs/tutorials/comments.rst index a436f9c24..f7338a753 100644 --- a/docs/tutorials/comments.rst +++ b/docs/tutorials/comments.rst @@ -1,25 +1,31 @@ Comment Extraction and Parsing ============================== -A common use for Reddit's API is to extract comments from submissions and use -them to perform keyword or phrase analysis. +A common use for Reddit's API is to extract comments from submissions and use them to +perform keyword or phrase analysis. As always, you need to begin by creating an instance of :class:`.Reddit`: .. code-block:: python - import asyncpraw + import asyncpraw - reddit = asyncpraw.Reddit(user_agent="Comment Extraction (by /u/USERNAME)", - client_id="CLIENT_ID", client_secret="CLIENT_SECRET", - username="USERNAME", password="PASSWORD") + reddit = asyncpraw.Reddit( + user_agent="Comment Extraction (by /u/USERNAME)", + client_id="CLIENT_ID", + client_secret="CLIENT_SECRET", + username="USERNAME", + password="PASSWORD", + ) -.. note:: If you are only analyzing public comments, entering a username and - password is optional. +.. note:: -In this document, we will detail the process of finding all the comments for a -given submission. If you instead want to process all comments on Reddit, or -comments belonging to one or more specific subreddits, please see + If you are only analyzing public comments, entering a username and password is + optional. + +In this document, we will detail the process of finding all the comments for a given +submission. If you instead want to process all comments on Reddit, or comments belonging +to one or more specific subreddits, please see :meth:`asyncpraw.models.reddit.subreddit.SubredditStream.comments`. .. _extracting_comments: @@ -30,8 +36,7 @@ Extracting comments with Async PRAW Assume we want to process the comments for this submission: https://www.reddit.com/r/funny/comments/3g1jfi/buttons/ -We first need to obtain a submission object. We can do that either with the -entire URL: +We first need to obtain a submission object. We can do that either with the entire URL: .. code-block:: python @@ -44,13 +49,13 @@ or with the submission's ID which comes after ``comments/`` in the URL: submission = await reddit.submission(id="3g1jfi") -With a submission object we can then interact with its :class:`.CommentForest` -through the submission's :attr:`~asyncpraw.models.Submission.comments` attribute. A -:class:`.CommentForest` is a list of top-level comments each of which contains -a :class:`.CommentForest` of replies. +With a submission object we can then interact with its :class:`.CommentForest` through +the submission's :attr:`~asyncpraw.models.Submission.comments` attribute. A +:class:`.CommentForest` is a list of top-level comments each of which contains a +:class:`.CommentForest` of replies. -If we wanted to output only the ``body`` of the top level comments in the -thread we could do: +If we wanted to output only the ``body`` of the top level comments in the thread we +could do: .. code-block:: python @@ -58,12 +63,11 @@ thread we could do: for top_level_comment in comments: print(top_level_comment.body) -While running this you will most likely encounter the exception -``AttributeError: 'MoreComments' object has no attribute 'body'``. This -submission's comment forest contains a number of :class:`.MoreComments` -objects. These objects represent the "load more comments", and "continue this -thread" links encountered on the website. While we could ignore -:class:`.MoreComments` in our code, like so: +While running this you will most likely encounter the exception ``AttributeError: +'MoreComments' object has no attribute 'body'``. This submission's comment forest +contains a number of :class:`.MoreComments` objects. These objects represent the "load +more comments", and "continue this thread" links encountered on the website. While we +could ignore :class:`.MoreComments` in our code, like so: .. code-block:: python @@ -78,24 +82,22 @@ thread" links encountered on the website. While we could ignore The ``replace_more`` method --------------------------- -In the previous snippet, we used ``isinstance`` to check whether the item -in the comment list was a :class:`.MoreComments` so that we could ignore it. -But there is a better way: the :class:`.CommentForest` object has a method -called :meth:`.replace_more`, which replaces or removes :class:`.MoreComments` -objects from the forest. - -Each replacement requires one network request, and its response may yield -additional :class:`.MoreComments` instances. As a result, by default, -:meth:`.replace_more` only replaces at most thirty-two :class:`.MoreComments` -instances -- all other instances are simply removed. The maximum number of -instances to replace can be configured via the ``limit`` parameter. -Additionally a ``threshold`` parameter can be set to only perform replacement -of :class:`.MoreComments` instances that represent a minimum number of -comments; it defaults to 0, meaning all :class:`.MoreComments` instances will -be replaced up to ``limit``. - -A ``limit`` of 0 simply removes all :class:`.MoreComments` from the forest. -The previous snippet can thus be simplified: +In the previous snippet, we used ``isinstance`` to check whether the item in the comment +list was a :class:`.MoreComments` so that we could ignore it. But there is a better way: +the :class:`.CommentForest` object has a method called :meth:`.replace_more`, which +replaces or removes :class:`.MoreComments` objects from the forest. + +Each replacement requires one network request, and its response may yield additional +:class:`.MoreComments` instances. As a result, by default, :meth:`.replace_more` only +replaces at most thirty-two :class:`.MoreComments` instances -- all other instances are +simply removed. The maximum number of instances to replace can be configured via the +``limit`` parameter. Additionally a ``threshold`` parameter can be set to only perform +replacement of :class:`.MoreComments` instances that represent a minimum number of +comments; it defaults to 0, meaning all :class:`.MoreComments` instances will be +replaced up to ``limit``. + +A ``limit`` of 0 simply removes all :class:`.MoreComments` from the forest. The previous +snippet can thus be simplified: .. code-block:: python @@ -104,12 +106,13 @@ The previous snippet can thus be simplified: for top_level_comment in comments: print(top_level_comment.body) -.. note:: Calling :meth:`.replace_more` is destructive. Calling it again on the - same submission instance has no effect. +.. note:: + + Calling :meth:`.replace_more` is destructive. Calling it again on the same + submission instance has no effect. -Meanwhile, a ``limit`` of ``None`` means that all :class:`.MoreComments` -objects will be replaced until there are none left, as long as they satisfy -the ``threshold``. +Meanwhile, a ``limit`` of ``None`` means that all :class:`.MoreComments` objects will be +replaced until there are none left, as long as they satisfy the ``threshold``. .. code-block:: python @@ -118,8 +121,8 @@ the ``threshold``. for top_level_comment in comments: print(top_level_comment.body) -Now we are able to successfully iterate over all the top-level comments. What -about their replies? We could output all second-level comments like so: +Now we are able to successfully iterate over all the top-level comments. What about +their replies? We could output all second-level comments like so: .. code-block:: python @@ -128,9 +131,9 @@ about their replies? We could output all second-level comments like so: for second_level_comment in top_level_comment.replies: print(second_level_comment.body) -However, the comment forest can be arbitrarily deep, so we'll want a more -robust solution. One way to iterate over a tree, or forest, is via a -breadth-first traversal using a queue: +However, the comment forest can be arbitrarily deep, so we'll want a more robust +solution. One way to iterate over a tree, or forest, is via a breadth-first traversal +using a queue: .. code-block:: python @@ -142,11 +145,11 @@ breadth-first traversal using a queue: print(comment.body) comment_queue.extend(comment.replies) -The above code will output all the top-level comments, followed by -second-level, third-level, etc. While it is awesome to be able to do your own -breadth-first traversals, :class:`.CommentForest` provides a convenience -method, :meth:`.list`, which returns a list of comments traversed in the same -order as the code above. Thus the above can be rewritten as: +The above code will output all the top-level comments, followed by second-level, +third-level, etc. While it is awesome to be able to do your own breadth-first +traversals, :class:`.CommentForest` provides a convenience method, :meth:`.list`, which +returns a list of comments traversed in the same order as the code above. Thus the above +can be rewritten as: .. code-block:: python @@ -156,10 +159,10 @@ order as the code above. Thus the above can be rewritten as: for comment in all_comments: print(comment.body) -You can now properly extract and parse all (or most) of the comments -belonging to a single submission. Combine this with :ref:`submission iteration -` and you can build some really cool stuff. +You can now properly extract and parse all (or most) of the comments belonging to a +single submission. Combine this with :ref:`submission iteration ` +and you can build some really cool stuff. -Finally, note that the value of ``submission.num_comments`` may not match up -100% with the number of comments extracted via Async PRAW. This discrepancy is -normal as that count includes deleted, removed, and spam comments. +Finally, note that the value of ``submission.num_comments`` may not match up 100% with +the number of comments extracted via Async PRAW. This discrepancy is normal as that +count includes deleted, removed, and spam comments. diff --git a/docs/tutorials/refresh_token.rst b/docs/tutorials/refresh_token.rst index 5670181ac..c6ddbb1b2 100644 --- a/docs/tutorials/refresh_token.rst +++ b/docs/tutorials/refresh_token.rst @@ -14,10 +14,11 @@ Working with Refresh Tokens Reddit OAuth2 Scopes -------------------- -Before working with refresh tokens you should decide which scopes your application requires. -If you want to use all scopes, you can use the special scope ``*``. +Before working with refresh tokens you should decide which scopes your application +requires. If you want to use all scopes, you can use the special scope ``*``. -To get an up-to-date listing of all Reddit scopes and their descriptions run the following: +To get an up-to-date listing of all Reddit scopes and their descriptions run the +following: .. code-block:: python @@ -25,7 +26,7 @@ To get an up-to-date listing of all Reddit scopes and their descriptions run the response = requests.get( "https://www.reddit.com/api/v1/scopes.json", - headers={"User-Agent": "fetch-scopes by u/bboe"} + headers={"User-Agent": "fetch-scopes by u/bboe"}, ) for scope, data in sorted(response.json().items()): @@ -33,7 +34,6 @@ To get an up-to-date listing of all Reddit scopes and their descriptions run the As of February 2021, the available scopes are: - ================ ====================================================================== Scope Description ================ ====================================================================== @@ -83,21 +83,22 @@ The following program can be used to obtain a refresh token with the desired sco .. literalinclude:: ../examples/obtain_refresh_token.py :language: python - .. _using_refresh_tokens: Using and Updating Refresh Tokens --------------------------------- -Reddit refresh tokens can be used only once. When an authorization is refreshed the existing refresh -token is consumed and a new access token and refresh token will be issued. While PRAW automatically -handles refreshing tokens when needed, it does not automatically handle the storage of the refresh -tokens. However, PRAW provides the facilities for you to manage your refresh tokens via custom -subclasses of :class:`.BaseTokenManager`. For trivial examples, PRAW provides the +Reddit refresh tokens can be used only once. When an authorization is refreshed the +existing refresh token is consumed and a new access token and refresh token will be +issued. While PRAW automatically handles refreshing tokens when needed, it does not +automatically handle the storage of the refresh tokens. However, PRAW provides the +facilities for you to manage your refresh tokens via custom subclasses of +:class:`.BaseTokenManager`. For trivial examples, PRAW provides the :class:`.FileTokenManager`. -The following program demonstrates how to prepare a file with an initial refresh token, and configure -PRAW to both use that refresh token, and keep the file up-to-date with a valid refresh token. +The following program demonstrates how to prepare a file with an initial refresh token, +and configure PRAW to both use that refresh token, and keep the file up-to-date with a +valid refresh token. .. literalinclude:: ../examples/use_file_token_manager.py :language: python diff --git a/docs/tutorials/reply_bot.rst b/docs/tutorials/reply_bot.rst index 5997421e8..0f22798a6 100644 --- a/docs/tutorials/reply_bot.rst +++ b/docs/tutorials/reply_bot.rst @@ -1,86 +1,83 @@ Submission Stream Reply Bot =========================== -Most redditors have seen bots in action on the site. Reddit bots can perform a -number of tasks including providing useful information, e.g., an Imperial to -Metric units bot; convenience, e.g., a link corrector bot; or analytical -information, e.g., redditor analyzer bot for writing complexity. +Most redditors have seen bots in action on the site. Reddit bots can perform a number of +tasks including providing useful information, e.g., an Imperial to Metric units bot; +convenience, e.g., a link corrector bot; or analytical information, e.g., redditor +analyzer bot for writing complexity. -PRAW provides a simple way to build your own bot using the python programming -language. As a result, it is little surprise that a majority of bots on Reddit -are powered by Async PRAW. +PRAW provides a simple way to build your own bot using the python programming language. +As a result, it is little surprise that a majority of bots on Reddit are powered by +Async PRAW. -With Async PRAW, there is now support for interacting with Reddit inside an -asynchronous environment, most commonly, Discord bots. +With Async PRAW, there is now support for interacting with Reddit inside an asynchronous +environment, most commonly, Discord bots. -This tutorial will show you how to build a bot that monitors a particular -subreddit, `r/AskReddit `_, for new -submissions containing simple questions and replies with an appropriate link to -lmgtfy_ (Let Me Google That For You). +This tutorial will show you how to build a bot that monitors a particular subreddit, +`r/AskReddit `_, for new submissions containing +simple questions and replies with an appropriate link to lmgtfy_ (Let Me Google That For +You). There are three key components we will address to perform this task: 1. Monitor new submissions. - -2. Analyze the title of each submission to see if it contains a simple - question. - +2. Analyze the title of each submission to see if it contains a simple question. 3. Reply with an appropriate lmgtfy_ link. LMGTFY Bot ---------- -The goal of the LMGTFY Bot is to point users in the right direction when they -ask a simple question that is unlikely to be upvoted or answered by other -users. +The goal of the LMGTFY Bot is to point users in the right direction when they ask a +simple question that is unlikely to be upvoted or answered by other users. Two examples of such questions are: 1. "What is the capital of Canada?" - 2. "How many feet are in a yard?" -Once we identify these questions, the LMGTFY Bot will reply to the submission -with an appropriate lmgtfy_ link. For the example -questions those links are: +Once we identify these questions, the LMGTFY Bot will reply to the submission with an +appropriate lmgtfy_ link. For the example questions those links are: 1. https://lmgtfy.com/?q=What+is+the+capital+of+Canada%3F - 2. https://lmgtfy.com/?q=How+many+feet+are+in+a+yard%3F - Step 1: Getting Started ~~~~~~~~~~~~~~~~~~~~~~~ -Access to Reddit's API requires a set of OAuth2 credentials. Those credentials -are obtained by registering an application with Reddit. To register an -application and receive a set of OAuth2 credentials please follow only the -"First Steps" section of Reddit's `OAuth2 Quick Start Example`_ wiki page. +Access to Reddit's API requires a set of OAuth2 credentials. Those credentials are +obtained by registering an application with Reddit. To register an application and +receive a set of OAuth2 credentials please follow only the "First Steps" section of +Reddit's `OAuth2 Quick Start Example`_ wiki page. -Once the credentials are obtained we can begin writing the LMGTFY Bot. Start by -creating an instance of :class:`.Reddit`: +Once the credentials are obtained we can begin writing the LMGTFY Bot. Start by creating +an instance of :class:`.Reddit`: .. code-block:: python import asyncpraw - reddit = asyncpraw.Reddit(user_agent="LMGTFY (by /u/USERNAME)", - client_id="CLIENT_ID", client_secret="CLIENT_SECRET", - username="USERNAME", password="PASSWORD") + reddit = asyncpraw.Reddit( + user_agent="LMGTFY (by /u/USERNAME)", + client_id="CLIENT_ID", + client_secret="CLIENT_SECRET", + username="USERNAME", + password="PASSWORD", + ) -In addition to the OAuth2 credentials, the username and password of the Reddit -account that registered the application are required. +In addition to the OAuth2 credentials, the username and password of the Reddit account +that registered the application are required. -.. note:: This example demonstrates use of a *script* type application. For - other application types please see Reddit's wiki page `OAuth2 App Types - `_. +.. note:: + This example demonstrates use of a *script* type application. For other application + types please see Reddit's wiki page `OAuth2 App Types + `_. Step 2: Monitoring New Submissions to /r/AskReddit ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -PRAW provides a convenient way to obtain new submissions to a given -subreddit. To indefinitely iterate over new submissions to a subreddit add: +PRAW provides a convenient way to obtain new submissions to a given subreddit. To +indefinitely iterate over new submissions to a subreddit add: .. code-block:: python @@ -89,25 +86,25 @@ subreddit. To indefinitely iterate over new submissions to a subreddit add: # do something with submission ... -Replace ``AskReddit`` with the name of another subreddit if you want to iterate -through its new submissions. Additionally multiple subreddits can be specified -by joining them with pluses, for example, ``AskReddit+NoStupidQuestions``. All -subreddits can be specified using the special name ``all``. +Replace ``AskReddit`` with the name of another subreddit if you want to iterate through +its new submissions. Additionally multiple subreddits can be specified by joining them +with pluses, for example, ``AskReddit+NoStupidQuestions``. All subreddits can be +specified using the special name ``all``. Step 3: Analyzing the Submission Titles ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Now that we have a stream of new submissions to r/AskReddit, it is time to see -if their titles contain a simple question. We naïvely define a simple question -as: +Now that we have a stream of new submissions to r/AskReddit, it is time to see if their +titles contain a simple question. We naïvely define a simple question as: 1. It must contain no more than ten words. - 2. It must contain one of the phrases "what is", "what are", or "who is". -.. warning:: These naïve criteria result in many false positives. It is - strongly recommended that you develop more precise heuristics before - launching a bot on any popular subreddits. +.. warning:: + + These naïve criteria result in many false positives. It is strongly recommended that + you develop more precise heuristics before launching a bot on any popular + subreddits. First we filter out titles that contain more than ten words: @@ -116,8 +113,7 @@ First we filter out titles that contain more than ten words: if len(submission.title.split()) > 10: return -We then check to see if the submission's title contains any of the desired -phrases: +We then check to see if the submission's title contains any of the desired phrases: .. code-block:: python @@ -128,43 +124,41 @@ phrases: # do something with a matched submission break -String comparison in Python is case sensitive. As a result, we only compare a -normalized version of the title to our lower-case question phrases. In this -case, "normalized" means only lower-case. +String comparison in Python is case sensitive. As a result, we only compare a normalized +version of the title to our lower-case question phrases. In this case, "normalized" +means only lower-case. The ``break`` at the end prevents us from matching more than once on a single -submission. For instance, what would happen without the ``break`` if a -submission's title was "Who is or what are buffalo?" +submission. For instance, what would happen without the ``break`` if a submission's +title was "Who is or what are buffalo?" Step 4: Automatically Replying to the Submission ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The LMGTFY Bot is nearly complete. We iterate through submissions, and find -ones that appear to be simple questions. All that is remaining is to reply to -those submissions with an appropriate lmgtfy_ link. - -First we will need to construct a working lmgtfy_ link. In essence we want to -pass the entire submission title to lmgtfy_. However, there are certain -characters that are not permitted in URLs or have other meanings. For instance, the -space character, " ", is not permitted, and the question mark, "?", has a -special meaning. Thus we will transform those into their URL-safe -representation so that a question like "What is the capital of Canada?" is -transformed into the link +The LMGTFY Bot is nearly complete. We iterate through submissions, and find ones that +appear to be simple questions. All that is remaining is to reply to those submissions +with an appropriate lmgtfy_ link. + +First we will need to construct a working lmgtfy_ link. In essence we want to pass the +entire submission title to lmgtfy_. However, there are certain characters that are not +permitted in URLs or have other meanings. For instance, the space character, " ", is not +permitted, and the question mark, "?", has a special meaning. Thus we will transform +those into their URL-safe representation so that a question like "What is the capital of +Canada?" is transformed into the link ``https://lmgtfy.com/?q=What+is+the+capital+of+Canada%3F``. -There are a number of ways we could accomplish this task. For starters we could -write a function to replace spaces with pluses, ``+``, and question marks with -``%3F``. However, there is even an easier way; using an existing built-in -function to do so. +There are a number of ways we could accomplish this task. For starters we could write a +function to replace spaces with pluses, ``+``, and question marks with ``%3F``. However, +there is even an easier way; using an existing built-in function to do so. -Add the following code where the "do something with a matched submission" -comment is located: +Add the following code where the "do something with a matched submission" comment is +located: .. code-block:: python from urllib.parse import quote_plus - reply_template = '[Let me google that for you](https://lmgtfy.com/?q={})' + reply_template = "[Let me google that for you](https://lmgtfy.com/?q={})" url_title = quote_plus(submission.title) reply_text = reply_template.format(url_title) @@ -175,59 +169,59 @@ Now that we have the reply text, replying to the submission is easy: await submission.reply(reply_text) -If all went well, your comment should have been made. If your bot account is -brand new, you will likely run into rate limit issues. These rate limits will -persist until that account acquires sufficient karma. +If all went well, your comment should have been made. If your bot account is brand new, +you will likely run into rate limit issues. These rate limits will persist until that +account acquires sufficient karma. Step 5: Cleaning Up The Code ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -While we have a working bot, we have added little segments here and there. If -we were to continue to do so in this fashion our code would be quite -unreadable. Let's clean it up some. +While we have a working bot, we have added little segments here and there. If we were to +continue to do so in this fashion our code would be quite unreadable. Let's clean it up +some. -The first thing we should do is put all of our import statements at the top of -the file. It is common to list built-in packages before third party ones: +The first thing we should do is put all of our import statements at the top of the file. +It is common to list built-in packages before third party ones: .. include:: ../examples/lmgtfy_bot.py - :code: python - :end-line: 3 + :code: python + :end-line: 3 Next we extract a few constants that are used in our script: .. include:: ../examples/lmgtfy_bot.py - :code: python - :start-line: 4 - :end-line: 6 + :code: python + :start-line: 4 + :end-line: 6 -We then extract the segment of code pertaining to processing a single -submission into its own function: +We then extract the segment of code pertaining to processing a single submission into +its own function: .. include:: ../examples/lmgtfy_bot.py - :code: python - :start-line: 18 - :end-line: 33 + :code: python + :start-line: 18 + :end-line: 33 -Observe that we added some comments and a ``print`` call. The ``print`` -addition informs us every time we are about to reply to a submission, which is -useful to ensure the script is running. +Observe that we added some comments and a ``print`` call. The ``print`` addition informs +us every time we are about to reply to a submission, which is useful to ensure the +script is running. -Next, it is a good practice to not have any top-level executable code in -case you want to turn your Python script into a Python module, i.e., import it -from another Python script or module. A common way to do that is to move the -top-level code to a ``main`` function: +Next, it is a good practice to not have any top-level executable code in case you want +to turn your Python script into a Python module, i.e., import it from another Python +script or module. A common way to do that is to move the top-level code to a ``main`` +function: .. include:: ../examples/lmgtfy_bot.py - :code: python - :start-line: 8 - :end-line: 16 + :code: python + :start-line: 8 + :end-line: 16 -Finally we need to call ``main`` only in the cases that this script is the one -being executed: +Finally we need to call ``main`` only in the cases that this script is the one being +executed: .. include:: ../examples/lmgtfy_bot.py - :code: python - :start-line: 35 + :code: python + :start-line: 35 The Complete LMGTFY Bot ~~~~~~~~~~~~~~~~~~~~~~~ @@ -235,9 +229,8 @@ The Complete LMGTFY Bot The following is the complete LMGTFY Bot: .. literalinclude:: ../examples/lmgtfy_bot.py - :language: python - + :language: python .. _lmgtfy: https://lmgtfy.com/ -.. _OAuth2 Quick Start Example: - https://github.com/reddit/reddit/wiki/OAuth2-Quick-Start-Example#first-steps + +.. _oauth2 quick start example: https://github.com/reddit/reddit/wiki/OAuth2-Quick-Start-Example#first-steps diff --git a/pre_push.py b/pre_push.py index 7f168da9f..6655a8464 100755 --- a/pre_push.py +++ b/pre_push.py @@ -19,6 +19,7 @@ def do_process(args, shell=False): Output failed message on non-zero exit and return False. Exit if command is not found. + """ print(f"Running: {' '.join(args)}") try: @@ -35,8 +36,9 @@ def do_process(args, shell=False): def run_static(): """Runs the static tests. - Returns a statuscode of 0 if everything ran correctly. - Otherwise, it will return statuscode 1 + Returns a statuscode of 0 if everything ran correctly. Otherwise, it will return + statuscode 1 + """ success = True # Formatters @@ -75,8 +77,9 @@ def run_static(): def run_unit(): """Runs the unit-tests. - Follows the behavior of the static tests, - where any failed tests cause pre_push.py to fail. + Follows the behavior of the static tests, where any failed tests cause pre_push.py + to fail. + """ return do_process(["pytest"]) @@ -87,6 +90,7 @@ def main(): usage: pre_push.py [-h] [-n] [-u] [-a] Run static and/or unit-tests + """ parser = argparse.ArgumentParser(description="Run static and/or unit-tests") parser.add_argument( diff --git a/tests/conftest.py b/tests/conftest.py index 6d816b72c..23a1a7bf9 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -168,5 +168,6 @@ def pytest_configure(): @pytest.fixture def tmp_path(request, tmp_path_factory): - """Manually create tmp_path fixture since asynctest does not play nicely with fixtures as args""" + # Manually create tmp_path fixture since asynctest does not play nicely with + # fixtures as args request.cls.tmp_path = _mk_tmp(request, tmp_path_factory) diff --git a/tests/integration/__init__.py b/tests/integration/__init__.py index 71bfa314e..c31293f53 100644 --- a/tests/integration/__init__.py +++ b/tests/integration/__init__.py @@ -65,6 +65,7 @@ def use_cassette(self, cassette_name=None, **kwargs): that are not equal to the dynamically generated name will be logged. :param kwargs: All keyword arguments for the main function (``VCR.use_cassette``). + """ dynamic_name = self.get_cassette_name() if cassette_name: diff --git a/tests/integration/test_github_actions.py b/tests/integration/test_github_actions.py index d38e1cb36..97881ef03 100644 --- a/tests/integration/test_github_actions.py +++ b/tests/integration/test_github_actions.py @@ -1,7 +1,8 @@ """A test that is run only by Github Actions -This test makes real network requests, so environment variables -should be specified in Github Actions. +This test makes real network requests, so environment variables should be specified in +Github Actions. + """ import os diff --git a/tools/check_documentation.py b/tools/check_documentation.py index b9e2231ec..1e172af64 100644 --- a/tools/check_documentation.py +++ b/tools/check_documentation.py @@ -15,11 +15,11 @@ class DocumentationChecker: """Checks for code block statements and attribute tables in subclasses. - Attribute exceptions holds all exceptions. All classes and subclasses in - the exceptions list will be ignored. + Attribute exceptions holds all exceptions. All classes and subclasses in the + exceptions list will be ignored. + + Attribute METHOD_EXCEPTIONS holds the names of methods that will be filtered out. - Attribute METHOD_EXCEPTIONS holds the names of methods that will be - filtered out. """ BASE_SEARCH_CLASS = RedditBase diff --git a/tools/static_word_checks.py b/tools/static_word_checks.py index 5c426a5ec..8e4a8f581 100644 --- a/tools/static_word_checks.py +++ b/tools/static_word_checks.py @@ -11,6 +11,7 @@ def __init__(self, replace: bool): """Initializes the class. :param replace: Whether or not to make replacements. + """ self.full_file_checks = [ self.check_for_double_syntax @@ -27,7 +28,9 @@ def check_for_double_syntax(self, filename: str, content: str) -> bool: :param filename: The name of the file to check & replace. :param content: The content of the file + :returns: A boolean with the status of the check + """ if ( os.path.join("asyncpraw", "const.py") in filename @@ -58,7 +61,9 @@ def check_for_noreturn(self, filename: str, line_number: int, content: str) -> b :param filename: The name of the file to check & replace. :param line_number: The line number :param content: The content of the line + :returns: A boolean with the status of the check + """ if "noreturn" in content.lower(): print( @@ -73,21 +78,23 @@ def run_checks(self) -> bool: The directory is assumed to be the asyncpraw directory located in the parent directory of the file, so if this file exists in - ``~/asyncpraw/tools/static_word_checks.py``, it will check ``~/asyncpraw/asyncpraw``. + ``~/asyncpraw/tools/static_word_checks.py``, it will check + ``~/asyncpraw/asyncpraw``. It runs the checks located in the ``self.full_file_checks`` and ``self.line_checks`` lists, with full file checks being run first. - Full-file checks are checks that can also fix the errors they find, - while the line checks can just warn about found errors. + Full-file checks are checks that can also fix the errors they find, while the + line checks can just warn about found errors. + + - Full file checks: - * Full file checks: + - :meth:`.check_for_double_syntax` - * :meth:`.check_for_double_syntax` + - Line checks - * Line checks + - :meth:`.check_for_noreturn` - * :meth:`.check_for_noreturn` """ status = True directory = os.path.abspath(os.path.join(__file__, "..", "..", "asyncpraw"))