#! /usr/bin/env python3 # encoding: utf-8 # ---------------------------------------------------------------- def flatten_dict(root, glue=" ", prefix=[]): lines = [] for k, v in root.items(): new_prefix = prefix + [k] if type(v) == dict: lines.extend(flatten_dict(v, glue, new_prefix)) else: lines.append((glue.join(new_prefix), v)) return lines # ---------------------------------------------------------------- def clamp(A, low, high): """ Clamps integer A to """ if A < low: return low elif A > high: return high else: return A # ---------------------------------------------------------------- import random PASSPHRASE_VOWELS = "aeiuAEU" PASSPHRASE_CONSONANTS = "bcdfghjkmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ23456789" def random_bytes(length): return open("/dev/urandom", "rb").read(length) def random_syllable(): return random.choice(PASSPHRASE_CONSONANTS) + random.choice(PASSPHRASE_VOWELS) + random.choice(PASSPHRASE_CONSONANTS) def random_word(syllables=3): parts = [] for _ in range(syllables): parts.append(random_syllable()) return "".join(parts) # ---------------------------------------------------------------- import hashlib def hash_password(p, hexdigest=True): h = hashlib.blake2b() h.update(p.encode("utf-8")) return h.hexdigest() if hexdigest else h.digest() # ---------------------------------------------------------------- class DeleteOverlay: pass def overlay_tree(base, overlay): """ For every key path in `overlay`, sets the leaf value of the same key path in `base`. Any missing non-leaf keys will be created. To delete a key, set its overlay value to DeleteOverlay. """ stack = [(base, overlay)] while stack: base_p, over_p = stack.pop() for k, v in over_p.items(): if v is DeleteOverlay: del base_p[k] else: if type(v) is dict: if k not in base_p or type(base_p[k]) is not dict: base_p[k] = {} stack.append((base_p[k], over_p[k])) else: base_p[k] = v