54 lines
1.8 KiB
Python
54 lines
1.8 KiB
Python
import random
|
|
import string
|
|
from hashlib import sha512
|
|
|
|
from flask import json
|
|
from sqlalchemy.ext.declarative import DeclarativeMeta
|
|
|
|
SIMPLE_CHARS = string.ascii_letters + string.digits
|
|
|
|
|
|
def get_random_string(length=32):
|
|
return ''.join(random.choice(SIMPLE_CHARS) for i in range(length))
|
|
|
|
|
|
def get_random_hash(length=64):
|
|
hash = sha512()
|
|
hash.update(get_random_string())
|
|
return hash.hexdigest()[:length]
|
|
|
|
|
|
def new_alchemy_encoder(revisit_self=False, fields_to_expand=[]):
|
|
_visited_objs = []
|
|
|
|
class AlchemyEncoder(json.JSONEncoder):
|
|
def default(self, obj):
|
|
if isinstance(obj.__class__, DeclarativeMeta):
|
|
# don't re-visit self
|
|
if revisit_self:
|
|
if obj in _visited_objs:
|
|
return None
|
|
_visited_objs.append(obj)
|
|
|
|
# go through each field in this SQLalchemy class
|
|
fields = {}
|
|
for field in [x for x in dir(obj) if not x.startswith('_') and x != 'metadata']:
|
|
val = obj.__getattribute__(field)
|
|
|
|
# is this field another SQLalchemy object, or a list of SQLalchemy objects?
|
|
if isinstance(val.__class__, DeclarativeMeta) or (
|
|
isinstance(val, list) and len(val) > 0 and isinstance(val[0].__class__, DeclarativeMeta)):
|
|
# unless we're expanding this field, stop here
|
|
if field not in fields_to_expand:
|
|
# not expanding this field: set it to None and continue
|
|
fields[field] = None
|
|
continue
|
|
|
|
fields[field] = val
|
|
# a json-encodable dict
|
|
return fields
|
|
|
|
return json.JSONEncoder.default(self, obj)
|
|
|
|
return AlchemyEncoder
|