o
    2g                     @  s   d Z ddlmZ ddlmZmZ ddlmZ ddlm	Z	 ddl
mZ e	r,ddlZddlZG d	d
 d
eZG dd deZG dd deZdS )a  Token Manager classes.

There should be a 1-to-1 mapping between an instance of a subclass of
:class:`.BaseTokenManager` and a :class:`.Reddit` instance.

A few proof of concept token manager classes are provided here, but it is expected that
PRAW users will create their own token manager classes suitable for their needs.

.. deprecated:: 7.4.0

    Tokens managers have been deprecated and will be removed in the near future.

    )annotations)ABCabstractmethod)Path)TYPE_CHECKING   )_deprecate_argsNc                   @  sR   e Zd ZdZedddZedddZedd
dZej	dddZdd Z
dS )BaseTokenManagerz)An abstract class for all token managers.
authorizerprawcore.auth.BaseAuthorizerc                 C     dS )az  Handle callback that is invoked after a refresh token is used.

        :param authorizer: The ``prawcore.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``.

        N selfr
   r   r   O/home/garg/my-data/venv/lib/python3.10/site-packages/praw/util/token_manager.pypost_refresh_callback        z&BaseTokenManager.post_refresh_callbackc                 C  r   )a  Handle callback that is invoked before refreshing PRAW's authorization.

        :param authorizer: The ``prawcore.Authorizer`` instance used containing
            ``access_token`` and ``refresh_token`` attributes.

        This callback can be used to inspect and modify the attributes of the
        ``prawcore.Authorizer`` instance, such as setting the ``refresh_token``.

        Nr   r   r   r   r   pre_refresh_callback,   r   z%BaseTokenManager.pre_refresh_callbackreturnpraw.Redditc                 C  s   | j S )z@Return the :class:`.Reddit` instance bound to the token manager._redditr   r   r   r   reddit8   s   zBaseTokenManager.redditvaluec                 C  s    | j d urd}t||| _ d S )Nz7'reddit' can only be set once and is done automatically)r   RuntimeError)r   r   msgr   r   r   r   =   s   

c                 C  s
   d| _ dS )z1Initialize a :class:`.BaseTokenManager` instance.Nr   r   r   r   r   __init__D   s   
zBaseTokenManager.__init__Nr
   r   )r   r   )r   r   )__name__
__module____qualname____doc__r   r   r   propertyr   setterr   r   r   r   r   r	      s    r	   c                      s6   e Zd ZdZd fddZddd	Zdd
dZ  ZS )FileTokenManagera  Provides a single-file based token manager.

    It is expected that the file with the initial ``refresh_token`` is created prior to
    use.

    .. warning::

        The same ``file`` should not be used by more than one instance of this class
        concurrently. Doing so may result in data corruption. Consider using
        :class:`.SQLiteTokenManager` if you want more than one instance of PRAW to
        concurrently manage a specific ``refresh_token`` chain.

    filenamestrc                   s   t    || _dS )z~Initialize a :class:`.FileTokenManager` instance.

        :param filename: The file the contains the refresh token.

        N)superr   	_filename)r   r&   	__class__r   r   r   X   s   

zFileTokenManager.__init__r
   r   c                 C  sB   t | jd}||j W d   dS 1 sw   Y  dS )z+Update the saved copy of the refresh token.wN)r   r)   openwriterefresh_tokenr   r
   fpr   r   r   r   a   s   "z&FileTokenManager.post_refresh_callbackc                 C  sP   |j du r&t| j }|  |_ W d   dS 1 sw   Y  dS dS )z%Load the refresh token from the file.N)r/   r   r)   r-   readstripr0   r   r   r   r   f   s
   
"z%FileTokenManager.pre_refresh_callback)r&   r'   r   )r   r    r!   r"   r   r   r   __classcell__r   r   r*   r   r%   I   s
    
	r%   c                      sf   e Zd ZdZeddd fddZdd Zdd
dZdddZdddZ	dddZ
dddZ  ZS )SQLiteTokenManagera  Provides a SQLite3 based token manager.

    Unlike, :class:`.FileTokenManager`, the initial database need not be created ahead
    of time, as it'll automatically be created on first use. However, initial refresh
    tokens will need to be registered via :meth:`.register` prior to use.

    .. warning::

        This class is untested on Windows because we encountered file locking issues in
        the test environment.

    databasekeyr'   c                  sJ   t    ddl}||| _| jd | jd | j  || _dS )a  Initialize a :class:`.SQLiteTokenManager` instance.

        :param database: The path to the SQLite database.
        :param key: The key used to locate the refresh token. This ``key`` can be
            anything. You might use the ``client_id`` if you expect to have unique a
            refresh token for each ``client_id``, or you might use a redditor's
            ``username`` if you're managing multiple users' authentications.

        r   NzACREATE TABLE IF NOT EXISTS tokens (id, refresh_token, updated_at)z<CREATE UNIQUE INDEX IF NOT EXISTS ux_tokens_id on tokens(id))r(   r   sqlite3connect_connectionexecutecommitr7   )r   r6   r7   r8   r*   r   r   r   {   s   


zSQLiteTokenManager.__init__c                 C  s.   | j d| jf}| }|d u rt|d S )N+SELECT refresh_token FROM tokens WHERE id=?r   )r:   r;   r7   fetchoneKeyError)r   cursorresultr   r   r   _get   s   zSQLiteTokenManager._getr/   c                 C  s"   | j d| j|f | j   dS )zSet the refresh token in the database.

        This function will overwrite an existing value if the corresponding ``key``
        already exists.

        z2REPLACE INTO tokens VALUES (?, ?, datetime('now'))N)r:   r;   r7   r<   )r   r/   r   r   r   _set   s
   zSQLiteTokenManager._setr   boolc                 C  s   | j d| jf}| duS )z7Return whether ``key`` already has a ``refresh_token``.r=   N)r:   r;   r7   r>   )r   r@   r   r   r   is_registered   s   z SQLiteTokenManager.is_registeredr
   r   c                 C  s   |  |j d|_dS )z)Update the refresh token in the database.N)rC   r/   r   r   r   r   r      s   
z(SQLiteTokenManager.post_refresh_callbackc                 C  s   |j du sJ |  |_ dS )z)Load the refresh token from the database.N)r/   rB   r   r   r   r   r      s   z'SQLiteTokenManager.pre_refresh_callbackc                 C  s(   | j d| j|f}| j   |jdkS )zRegister the initial refresh token in the database.

        :returns: ``True`` if ``refresh_token`` is saved to the database, otherwise,
            ``False`` if there is already a ``refresh_token`` for the associated
            ``key``.

        z;INSERT OR IGNORE INTO tokens VALUES (?, ?, datetime('now'))r   )r:   r;   r7   r<   rowcount)r   r/   r@   r   r   r   register   s   

zSQLiteTokenManager.register)r6   r'   r7   r'   )r/   r'   )r   rD   r   )r/   r'   r   rD   )r   r    r!   r"   r   r   rB   rC   rE   r   r   rG   r4   r   r   r*   r   r5   m   s    
	


	r5   )r"   
__future__r   abcr   r   pathlibr   typingr    r   prawcoreprawr	   r%   r5   r   r   r   r   <module>   s    ,$