69 lines
1.5 KiB
Python
69 lines
1.5 KiB
Python
# scopes.util
|
|
|
|
import base64
|
|
from collections.abc import Iterable
|
|
import hashlib
|
|
from secrets import choice
|
|
import string
|
|
|
|
# symbols and keywords
|
|
|
|
class Symbol(str):
|
|
|
|
def __repr__(self):
|
|
return f'<{self}>'
|
|
|
|
class Symbols:
|
|
|
|
def __init__(self, ns=None):
|
|
self.__prefix = ns + '.' if ns else ''
|
|
|
|
def __call__(self, *keys):
|
|
for segment in keys:
|
|
for key in segment.split():
|
|
if not hasattr(self, key):
|
|
setattr(self, key, Symbol(self.__prefix + key))
|
|
return self
|
|
|
|
def __getattr__(self, k):
|
|
raise AttributeError(k)
|
|
|
|
def __getitem__(self, k):
|
|
return getattr(self, k)
|
|
|
|
keywords = Symbols()
|
|
|
|
# list / iterable utilities
|
|
|
|
def flatten(*it, ignore_none=False):
|
|
accu = []
|
|
def doit(it):
|
|
if ignore_none and it is None:
|
|
return
|
|
if isinstance(it, Iterable):
|
|
for t in it:
|
|
doit(t)
|
|
else:
|
|
accu.append(it)
|
|
doit(it)
|
|
return accu
|
|
|
|
# random strings, hashes, encodings
|
|
# for authentication, encryption, and other purposes
|
|
|
|
BASE = string.ascii_letters + string.digits
|
|
BASE2 = BASE + '-._~'
|
|
|
|
def rndstr(size=16):
|
|
return ''.join([choice(BASE) for _ in range(size)])
|
|
|
|
def rndstr2(size=64):
|
|
return ''.join([choice(BASE2) for _ in range(size)])
|
|
|
|
def b64e(b):
|
|
return base64.urlsafe_b64encode(b).rstrip(b'=')
|
|
|
|
def hashS256(s):
|
|
h = hashlib.sha256(s.encode('ascii')).digest()
|
|
return b64e(h).decode('ascii')
|
|
|