Skip to content

Commit c280752

Browse files
committed
Deprecate token managers
1 parent bb0e008 commit c280752

File tree

9 files changed

+59
-73
lines changed

9 files changed

+59
-73
lines changed

CHANGES.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,13 @@ Unreleased
1414
- :meth:`.Inbox.mark_all_read` to mark all messages as read with one API call.
1515
- :meth:`~.InboxableMixin.unblock_subreddit` to unblock a subreddit.
1616
- :meth:`.update_crowd_control_level` to update the crowd control level of a post.
17+
- The configuration setting ``refresh_token`` has been added back. See
18+
https://www.reddit.com/r/redditdev/comments/olk5e6/followup_oauth2_api_changes_regarding_refresh/
19+
for more info.
20+
21+
**Deprecated**
22+
23+
- :class:`.Reddit` keyword argument ``token_manager``.
1724

1825
7.3.0 (2021/06/17)
1926
------------------

docs/getting_started/authentication.rst

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,3 +249,29 @@ such as in installed applications where the end user could retrieve the ``client
249249
from each other (as the supplied device id *should* be a unique string per both
250250
device (in the case of a web app, server) and user (in the case of a web app,
251251
browser session).
252+
253+
.. _using_refresh_tokens:
254+
255+
Using a Saved Refresh Token
256+
---------------------------
257+
258+
A saved refresh token can be used to immediately obtain an authorized instance of
259+
:class:`.Reddit` like so:
260+
261+
.. code-block:: python
262+
263+
reddit = praw.Reddit(
264+
client_id="SI8pN3DSbt0zor",
265+
client_secret="xaxkj7HNh8kwg8e5t4m6KvSrbTI",
266+
refresh_token="WeheY7PwgeCZj4S3QgUcLhKE5S2s4eAYdxM",
267+
user_agent="testscript by u/fakebot3",
268+
)
269+
print(reddit.auth.scopes())
270+
271+
The output from the above code displays which scopes are available on the
272+
:class:`.Reddit` instance.
273+
274+
.. note::
275+
276+
Observe that ``redirect_uri`` does not need to be provided in such cases. It is only
277+
needed when :meth:`.url` is used.

docs/tutorials/refresh_token.rst

Lines changed: 0 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,6 @@
33
Working with Refresh Tokens
44
===========================
55

6-
.. note::
7-
8-
The process for using refresh tokens is in the process of changing on Reddit's end.
9-
This documentation has been updated to be aligned with the future of how Reddit
10-
handles refresh tokens, and will be the only supported method in PRAW 8+. For more
11-
information please see:
12-
https://old.reddit.com/r/redditdev/comments/kvzaot/oauth2_api_changes_upcoming/
13-
146
Reddit OAuth2 Scopes
157
--------------------
168

@@ -82,33 +74,3 @@ The following program can be used to obtain a refresh token with the desired sco
8274

8375
.. literalinclude:: ../examples/obtain_refresh_token.py
8476
:language: python
85-
86-
.. _using_refresh_tokens:
87-
88-
Using and Updating Refresh Tokens
89-
---------------------------------
90-
91-
Reddit refresh tokens can be used only once. When an authorization is refreshed the
92-
existing refresh token is consumed and a new access token and refresh token will be
93-
issued. While PRAW automatically handles refreshing tokens when needed, it does not
94-
automatically handle the storage of the refresh tokens. However, PRAW provides the
95-
facilities for you to manage your refresh tokens via custom subclasses of
96-
:class:`.BaseTokenManager`. For trivial examples, PRAW provides the
97-
:class:`.FileTokenManager`.
98-
99-
The following program demonstrates how to prepare a file with an initial refresh token,
100-
and configure PRAW to both use that refresh token, and keep the file up-to-date with a
101-
valid refresh token.
102-
103-
.. literalinclude:: ../examples/use_file_token_manager.py
104-
:language: python
105-
106-
.. _sqlite_token_manager:
107-
108-
SQLiteTokenManager
109-
~~~~~~~~~~~~~~~~~~
110-
111-
For more complex examples, PRAW provides the :class:`.SQLiteTokenManager`.
112-
113-
.. literalinclude:: ../examples/use_sqlite_token_manager.py
114-
:language: python

praw/config.py

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import sys
55
from threading import Lock
66
from typing import Optional
7-
from warnings import warn
87

98
from .exceptions import ClientException
109

@@ -85,21 +84,11 @@ def __init__(
8584
self.custom = dict(Config.CONFIG.items(site_name), **settings)
8685

8786
self.client_id = self.client_secret = self.oauth_url = None
88-
self.reddit_url = self.redirect_uri = None
87+
self.reddit_url = self.refresh_token = self.redirect_uri = None
8988
self.password = self.user_agent = self.username = None
9089

9190
self._initialize_attributes()
9291

93-
self._do_not_use_refresh_token = self._fetch_or_not_set("refresh_token")
94-
if self._do_not_use_refresh_token != self.CONFIG_NOT_SET:
95-
warn(
96-
"The ``refresh_token`` configuration setting is deprecated and will be"
97-
" removed in PRAW 8. Please use ``token_manager`` to manage your"
98-
" refresh tokens.",
99-
category=DeprecationWarning,
100-
stacklevel=2,
101-
)
102-
10392
def _fetch(self, key):
10493
value = self.custom[key]
10594
del self.custom[key]

praw/models/auth.py

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -105,20 +105,13 @@ def url(
105105
whom the URL was generated for.
106106
:param duration: Either ``permanent`` or ``temporary`` (default: permanent).
107107
``temporary`` authorizations generate access tokens that last only 1 hour.
108-
``permanent`` authorizations additionally generate a single-use refresh
109-
token with a significantly longer expiration (~1 year) that is to be used to
110-
fetch a new set of tokens. This value is ignored when ``implicit=True``.
108+
``permanent`` authorizations additionally generate a refresh token that
109+
expires 1 year after the last use and can be used indefinitely to generate
110+
new hour-long access tokens. This value is ignored when ``implicit=True``.
111111
:param implicit: For **installed** applications, this value can be set to use
112112
the implicit, rather than the code flow. When True, the ``duration``
113113
argument has no effect as only temporary tokens can be retrieved.
114114
115-
.. note::
116-
117-
Reddit's ``refresh_tokens`` currently are reusable, and do not expire.
118-
However, that behavior is likely to change in the near future so it's best
119-
to no longer rely upon it:
120-
https://old.reddit.com/r/redditdev/comments/kvzaot/oauth2_api_changes_upcoming/
121-
122115
"""
123116
authenticator = self._reddit._read_only_core._authorizer._authenticator
124117
if authenticator.redirect_uri is self._reddit.config.CONFIG_NOT_SET:

praw/reddit.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -420,9 +420,16 @@ def _check_for_update(self):
420420

421421
def _prepare_common_authorizer(self, authenticator):
422422
if self._token_manager is not None:
423-
if self.config._do_not_use_refresh_token != self.config.CONFIG_NOT_SET:
423+
warn(
424+
"Token managers have been depreciated and will be removed in the near"
425+
" future. See https://www.reddit.com/r/redditdev/comments/olk5e6/"
426+
"followup_oauth2_api_changes_regarding_refresh/ for more details.",
427+
category=DeprecationWarning,
428+
stacklevel=2,
429+
)
430+
if self.config.refresh_token:
424431
raise TypeError(
425-
"legacy ``refresh_token`` setting cannot be provided when providing"
432+
"``refresh_token`` setting cannot be provided when providing"
426433
" ``token_manager``"
427434
)
428435

@@ -432,9 +439,9 @@ def _prepare_common_authorizer(self, authenticator):
432439
post_refresh_callback=self._token_manager.post_refresh_callback,
433440
pre_refresh_callback=self._token_manager.pre_refresh_callback,
434441
)
435-
elif self.config._do_not_use_refresh_token != self.config.CONFIG_NOT_SET:
442+
elif self.config.refresh_token != self.config.CONFIG_NOT_SET:
436443
authorizer = Authorizer(
437-
authenticator, refresh_token=self.config._do_not_use_refresh_token
444+
authenticator, refresh_token=self.config.refresh_token
438445
)
439446
else:
440447
self._core = self._read_only_core

praw/util/token_manager.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
A few proof of concept token manager classes are provided here, but it is expected that
77
PRAW users will create their own token manager classes suitable for their needs.
88
9-
See :ref:`using_refresh_tokens` for examples on how to leverage these classes.
9+
.. deprecated:: 7.3.0
10+
11+
Tokens managers have been depreciated and will be removed in the near future.
1012
1113
"""
1214
import sqlite3
@@ -100,7 +102,6 @@ class SQLiteTokenManager(BaseTokenManager):
100102
Unlike, :class:`.FileTokenManager`, the initial database need not be created ahead
101103
of time, as it'll automatically be created on first use. However, initial
102104
``refresh_tokens`` will need to be registered via :meth:`.register` prior to use.
103-
See :ref:`sqlite_token_manager` for an example of use.
104105
105106
.. warning::
106107

tests/unit/test_deprecations.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from praw import Reddit
66
from praw.exceptions import APIException, WebSocketException
77
from praw.models.reddit.user_subreddit import UserSubreddit
8+
from praw.util.token_manager import FileTokenManager
89

910
from . import UnitTest
1011

@@ -59,20 +60,20 @@ def test_gild_method(self):
5960
self.reddit.submission("1234").gild()
6061
assert excinfo.value.args[0] == "`.gild` has been renamed to `.award`."
6162

62-
def test_reddit_user_me_read_only(self):
63-
with pytest.raises(DeprecationWarning):
64-
self.reddit.user.me()
65-
66-
def test_reddit_refresh_token(self):
63+
def test_reddit_token_manager(self):
6764
with pytest.raises(DeprecationWarning):
6865
Reddit(
6966
client_id="dummy",
7067
client_secret=None,
7168
redirect_uri="dummy",
72-
refresh_token="dummy",
7369
user_agent="dummy",
70+
token_manager=FileTokenManager("name"),
7471
)
7572

73+
def test_reddit_user_me_read_only(self):
74+
with pytest.raises(DeprecationWarning):
75+
self.reddit.user.me()
76+
7677
def test_user_subreddit_as_dict(self):
7778
user_subreddit = UserSubreddit(None, display_name="test")
7879
with pytest.deprecated_call() as warning_info:

tests/unit/test_reddit.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ def test_conflicting_settings(self):
8888
)
8989
assert (
9090
str(excinfo.value)
91-
== "legacy ``refresh_token`` setting cannot be provided when providing ``token_manager``"
91+
== "``refresh_token`` setting cannot be provided when providing ``token_manager``"
9292
)
9393

9494
def test_context_manager(self):

0 commit comments

Comments
 (0)