# Path: flask_dance/consumer/storage/session.py
# class SessionStorage(BaseStorage):
#     """
#     The default storage backend. Stores and retrieves OAuth tokens using
#     the :ref:`Flask session <flask:sessions>`.
#     """
# 
#     def __init__(self, key="{bp.name}_oauth_token"):
#         """
#         Args:
#             key (str): The name to use as a key for storing the OAuth token in the
#                 Flask session. This string will have ``.format(bp=self.blueprint)``
#                 called on it before it is used. so you can refer to information
#                 on the blueprint as part of the key. For example, ``{bp.name}``
#                 will be replaced with the name of the blueprint.
#         """
#         self.key = key
# 
#     def get(self, blueprint):
#         key = self.key.format(bp=blueprint)
#         return flask.session.get(key)
# 
#     def set(self, blueprint, token):
#         key = self.key.format(bp=blueprint)
#         flask.session[key] = token
# 
#     def delete(self, blueprint):
#         key = self.key.format(bp=blueprint)
#         del flask.session[key]
# 
# Path: flask_dance/utils.py
# def getattrd(obj, name, default=sentinel):
#     """
#     Same as getattr(), but allows dot notation lookup
#     Source: http://stackoverflow.com/a/14324459
#     """
#     try:
#         return functools.reduce(getattr, name.split("."), obj)
#     except AttributeError as e:
#         if default is not sentinel:
#             return default
#         raise
# 
# def timestamp_from_datetime(dt):
#     """
#     Given a datetime, in UTC, return a float that represents the timestamp for
#     that datetime.
# 
#     http://stackoverflow.com/questions/8777753/converting-datetime-date-to-utc-timestamp-in-python#8778548
#     """
#     dt = dt.replace(tzinfo=utc)
#     if hasattr(dt, "timestamp") and callable(dt.timestamp):
#         return dt.replace(tzinfo=utc).timestamp()
#     return (dt - datetime(1970, 1, 1, tzinfo=utc)).total_seconds()
# 
# def invalidate_cached_property(obj, name):
#     obj.__dict__[name] = _missing


import warnings
import flask
from datetime import datetime, timedelta
from abc import ABCMeta, abstractmethod, abstractproperty
from werkzeug.datastructures import CallbackDict
from flask.signals import Namespace
from flask_dance.consumer.storage.session import SessionStorage
from flask_dance.utils import (
    getattrd,
    timestamp_from_datetime,
    invalidate_cached_property,
)
        """
        _token = self.storage.get(self)
        if _token and _token.get("expires_in") and _token.get("expires_at"):
            # Update the `expires_in` value, so that requests-oauthlib
            # can handle automatic token refreshing. Assume that
            # `expires_at` is a valid Unix timestamp.
            expires_at = datetime.utcfromtimestamp(_token["expires_at"])
            expires_in = expires_at - datetime.utcnow()
            _token["expires_in"] = expires_in.total_seconds()
        return _token

    @token.setter
    def token(self, value):
        _token = value
        if _token and _token.get("expires_in"):
            # Set the `expires_at` value, overwriting any value
            # that may already be there.
            delta = timedelta(seconds=_token["expires_in"])
            expires_at = datetime.utcnow() + delta
            _token["expires_at"] = timestamp_from_datetime(expires_at)
        self.storage.set(self, _token)
        try:
            invalidate_cached_property(self.session, "token")
        except KeyError:
            pass

    @token.deleter
    def token(self):
        self.storage.delete(self)
        try:

# Path: flask_dance/consumer/storage/session.py
# class SessionStorage(BaseStorage):
#     """
#     The default storage backend. Stores and retrieves OAuth tokens using
#     the :ref:`Flask session <flask:sessions>`.
#     """
# 
#     def __init__(self, key="{bp.name}_oauth_token"):
#         """
#         Args:
#             key (str): The name to use as a key for storing the OAuth token in the
#                 Flask session. This string will have ``.format(bp=self.blueprint)``
#                 called on it before it is used. so you can refer to information
#                 on the blueprint as part of the key. For example, ``{bp.name}``
#                 will be replaced with the name of the blueprint.
#         """
#         self.key = key
# 
#     def get(self, blueprint):
#         key = self.key.format(bp=blueprint)
#         return flask.session.get(key)
# 
#     def set(self, blueprint, token):
#         key = self.key.format(bp=blueprint)
#         flask.session[key] = token
# 
#     def delete(self, blueprint):
#         key = self.key.format(bp=blueprint)
#         del flask.session[key]
# 
# Path: flask_dance/utils.py
# def getattrd(obj, name, default=sentinel):
#     """
#     Same as getattr(), but allows dot notation lookup
#     Source: http://stackoverflow.com/a/14324459
#     """
#     try:
#         return functools.reduce(getattr, name.split("."), obj)
#     except AttributeError as e:
#         if default is not sentinel:
#             return default
#         raise
# 
# def timestamp_from_datetime(dt):
#     """
#     Given a datetime, in UTC, return a float that represents the timestamp for
#     that datetime.
# 
#     http://stackoverflow.com/questions/8777753/converting-datetime-date-to-utc-timestamp-in-python#8778548
#     """
#     dt = dt.replace(tzinfo=utc)
#     if hasattr(dt, "timestamp") and callable(dt.timestamp):
#         return dt.replace(tzinfo=utc).timestamp()
#     return (dt - datetime(1970, 1, 1, tzinfo=utc)).total_seconds()
# 
# def invalidate_cached_property(obj, name):
#     obj.__dict__[name] = _missing


# Path: flask_dance/consumer/base.py
import warnings
import flask
from datetime import datetime, timedelta
from abc import ABCMeta, abstractmethod, abstractproperty
from werkzeug.datastructures import CallbackDict
from flask.signals import Namespace
from flask_dance.consumer.storage.session import SessionStorage
from flask_dance.utils import (
    getattrd,
    timestamp_from_datetime,
    invalidate_cached_property,
)

        """
        _token = self.storage.get(self)
        if _token and _token.get("expires_in") and _token.get("expires_at"):
            # Update the `expires_in` value, so that requests-oauthlib
            # can handle automatic token refreshing. Assume that
            # `expires_at` is a valid Unix timestamp.
            expires_at = datetime.utcfromtimestamp(_token["expires_at"])
            expires_in = expires_at - datetime.utcnow()
            _token["expires_in"] = expires_in.total_seconds()
        return _token

    @token.setter
    def token(self, value):
        _token = value
        if _token and _token.get("expires_in"):
            # Set the `expires_at` value, overwriting any value
            # that may already be there.
            delta = timedelta(seconds=_token["expires_in"])
            expires_at = datetime.utcnow() + delta
            _token["expires_at"] = timestamp_from_datetime(expires_at)
        self.storage.set(self, _token)
        try:
            invalidate_cached_property(self.session, "token")
        except KeyError:
            pass

    @token.deleter
    def token(self):
        self.storage.delete(self)
        try:

            invalidate_cached_property(self.session, "token")