#!/usr/bin/env python from copy import deepcopy class Empty: pass def get_dic(base, over_wrt): d = base.copy() d.update( over_wrt ) return d def to_attr(e, dic={}, **kwds): vars( e ).update( get_dic( dic, kwds ) ) return e new = lambda dic={}, **kwds: to_attr( Empty(), dic, **kwds ) new_kwds = new def add(e, dic={}, **kwds): d = get_dic( get_dic( dic, kwds ), vars( e ) ) vars( e ).update( d ) return e copy = lambda e: new( deepcopy( vars( e ) ) ) def update(targ, add): # not recursive dic = vars( targ ) dic.update( vars( add ) ) is_empty = lambda o: isinstance(o, Empty) def call(f, args=(), dv=None): return f( *args ) if f else dv def attr_call(e, attr, args=(), dv=None): if not e: return dv f = getattr( e, attr, None ) return call( f, args, dv ) def to_dic(o): t = type( o ) if t == list: return list( map( to_dic, o ) ) if t == dict: f = lambda kv: ( kv[0], to_dic( kv[1] ) ) return dict( map( f, o.items() ) ) if is_empty( o ): return to_dic( vars( o ) ) return o def from_dic(o): t = type( o ) if t == list: return list( map( from_dic, o ) ) if t == dict: f = lambda kv: ( kv[0], from_dic( kv[1] ) ) return new( dict( map( f, o.items() ) ) ) if is_empty( o ): return from_dic( vars( o ) ) return o def kwds_pop(targ_dic, **kwds): for k in kwds.keys(): if k in targ_dic: kwds[ k ] = targ_dic.pop( k ) return new( kwds ) def chg_new(v, f=None, fv=None): e = new( v=v, prev=None, chg=None ) def set(v): e.chg = e.v != v if e.chg: e.prev = e.v e.v = v if f: f( e ) if fv: fv( e.v ) return e.chg return to_attr( e, locals() ) # EOF