def token_info(token, refresh=True, refresh_cb=None, session=None):
session = session or HTTP_SESSION<EOL>params = dict(access_token=token.access_token)<EOL>resp = session.get(TOKEN_INFO_URL, params=params)<EOL>if resp.status_code != <NUM_LIT:200>:<EOL><INDENT>if refresh:<EOL><INDENT>token = refresh_token(token, session=session)<EOL>if refresh_cb is not None:<EOL><INDENT>try:<EOL><INDENT>refresh_cb(token)<EOL><DEDENT>except Exception:<EOL><INDENT>LOGGER.exception('<STR_LIT>')<EOL><DEDENT><DEDENT>info = token_info(token, refresh=False, session=session)<EOL>info.update(refreshed=True)<EOL>return info<EOL><DEDENT>raise OAuthTokenRefreshRequiredError()<EOL><DEDENT>info = __coerce_token_info(resp.json())<EOL>info.update(token=token, refreshed=False)<EOL>return nameddict(info)<EOL>
:param OAuthToken token

:param bool refresh:
  whether to attempt to refresh the OAuth token if it expired.
  default is `True`.

:param refresh_cb:
  If specified, a callable object which is given the new token
  in parameter if it has been refreshed.

:param requests.Session session:
  Optional `requests` session to use.

:return:
  token information. see
  https://developers.google.com/identity/protocols/OAuth2UserAgent#tokeninfo-validation
  - `scope`: this field is not a space-delimited set of scopes
     but a real Python `set`.
  - `token`: additional field that provides the `OAuthToken`
  - `refreshed`: boolean that will tell if the token has been refreshed
:rtype: nameddict