Source code for redditwarp.auth.grants
from __future__ import annotations
from typing import TYPE_CHECKING, Mapping, ClassVar
if TYPE_CHECKING:
from typing import Iterator, Optional
from dataclasses import dataclass, field
[docs]@dataclass(frozen=True)
class AuthorizationGrant(Mapping[str, str]):
"""A class to construct authorization grant mappings conveniently.
An authorization grant is a credential representing the resource
owner's authorization that's used to exchange for a bearer token.
An empty string should be treated the same as `None` in all fields
annotated as `Optional`. The annotations reflect the field value
requirements of the various grants types defined in the OAuth2 spec.
"""
GRANT_TYPE: ClassVar[str] = ''
_d: dict[str, str] = field(init=False, repr=False, default_factory=dict)
def __post_init__(self) -> None:
self._d['grant_type'] = self.GRANT_TYPE
self._d.update({
k: v
for k, v in vars(self).items()
if not k.startswith('_')
if v
})
def __contains__(self, item: object) -> bool:
return item in self._d
def __iter__(self) -> Iterator[str]:
return iter(self._d)
def __len__(self) -> int:
return len(self._d)
def __getitem__(self, key: str) -> str:
return self._d[key]
[docs]@dataclass(frozen=True)
class AuthorizationCodeGrant(AuthorizationGrant):
GRANT_TYPE: ClassVar[str] = 'authorization_code'
code: str
redirect_uri: Optional[str]
client_id: Optional[str] = None
[docs]@dataclass(frozen=True)
class ResourceOwnerPasswordCredentialsGrant(AuthorizationGrant):
GRANT_TYPE: ClassVar[str] = 'password'
username: str
password: str
scope: Optional[str] = None
[docs]@dataclass(frozen=True)
class ClientCredentialsGrant(AuthorizationGrant):
GRANT_TYPE: ClassVar[str] = 'client_credentials'
scope: Optional[str] = None
[docs]@dataclass(frozen=True)
class RefreshTokenGrant(AuthorizationGrant):
GRANT_TYPE: ClassVar[str] = 'refresh_token'
refresh_token: str
scope: Optional[str] = None