Source code for hmrc.auth.token
"""HMRC API token storage"""
from dataclasses import dataclass, InitVar
import fcntl
import json
import os
import stat
from typing import TextIO
__all__ = [
'HmrcTokenStorage',
'HmrcTokenFileStorage',
]
[docs]@dataclass
class HmrcTokenStorage:
"""OAuth2 token storage"""
token: dict = None
"""Token value"""
def __post_init__(self):
# Automatically load token if not explicitly specified
if self.token is None:
self.token = {}
self.load()
[docs] def load(self):
"""Load token from storage"""
return self.token
[docs] def save(self, token=None):
"""Save token to storage"""
if token is not None:
self.token = token
[docs] def delete(self):
"""Delete token from storage"""
self.save({})
[docs] def close(self):
"""Close storage medium"""
def __enter__(self):
return self
def __exit__(self, *exc):
self.close()
[docs]@dataclass
class HmrcTokenFileStorage(HmrcTokenStorage):
"""OAuth2 token storage in a local JSON file"""
file: TextIO = None
"""File used to store JSON representation of OAuth2 token"""
path: InitVar[str] = None
"""Path to file"""
def __post_init__(self, path):
# pylint: disable=arguments-differ
# Open/create file if no explicit file was provided
if self.file is None:
if path is None:
path = os.path.expanduser('~/.hmrc.token')
fd = os.open(path, (os.O_RDWR | os.O_CREAT),
(stat.S_IRUSR | stat.S_IWUSR))
self.file = open(fd, 'a+t', encoding='utf8')
super().__post_init__()
[docs] def load(self):
"""Load token from JSON file"""
try:
fcntl.lockf(self.file.fileno(), fcntl.LOCK_SH)
self.file.seek(0)
data = self.file.read()
finally:
fcntl.lockf(self.file.fileno(), fcntl.LOCK_UN)
self.token = json.loads(data) if data else {}
return super().load()
[docs] def save(self, token=None):
"""Save token to JSON file"""
super().save(token)
data = json.dumps(self.token)
try:
fcntl.lockf(self.file.fileno(), fcntl.LOCK_EX)
self.file.seek(0)
self.file.truncate(0)
self.file.write(data)
self.file.flush()
finally:
fcntl.lockf(self.file.fileno(), fcntl.LOCK_UN)
[docs] def close(self):
"""Close file"""
self.file.close()