<commit_before>import numpy as np
import numpy.matlib
import scipy as sp
import scipy.io as sio
import inspect
import pdb
from numbers import Number

import warnings
import pdb

singleton = None

class Result:
    def __init__(this, name, passes=0, total=0):
        this.name   = name
        this.passes = float(passes)
        this.total  = float(total)

    def __iadd__(this, that):
        this.passes = this.passes + that.passes
        this.total  = this.total  + that.total
        return this

    def passed(this):
        return this.passes == this.total

    def __repr__(this):
        fr = 0.0
        if this.total > 0:
            fr = this.passes / this.total
        return "%s: %d%% pass (%d/%d)" % (this.name, round(fr*100.0), this.passes, this.total )

class Numnum:
        def __init__(this):
            this.idxn  = 0
            this.idxu  = 0
            this.ids   = {}
            this.ctx   = []
            this.gid   = 0
            this.state = {}
            this.mode  = 0
            this.unit  = 0
            this.run   = None
            this.depth = 0

        def push(this):
            """ push new context onto stack """
            name = caller(1)
            if name in this.ids:
                this.ids[name] = this.ids[name] + 1
            else:
                this.ids[name] = 1
            ctx = {}
            ctx["name"] = name
            ctx["run"]  = this.ids[name]
            this.ctx.append(ctx)

        def pop(this):
            """ pop context off of stack """
            ctx = this.ctx.pop()
            if this.mode > 0:
                if ctx["name"] not in this.state:
                    this.state[ctx["name"]] = []

                runs = this.state[ctx["name"]]

                if ctx["run"] == len(runs)+1:
                    runs.append(ctx)
                else:
                    raise Exception("wtf: %d ~ %d" % (ctx["run"] , len(runs)))
                # this.state[ctx.name] = runs

        def validate(this, str, *args):
            ctx = this.ctx[-1]

            if this.mode > 0:
                ctx[str] = args
            else:
                funs = this.state[ctx["name"]]
                if type(funs) != list:
                    funs = [funs]
                fun  = funs[ ctx["run"] - 1 ]
                vals = fun[str]
                this._validate(vals, *args)
            # this.ctx{end} = ctx;

        def _validate(this, vals, *args):
                if len(vals) != len(args):
                    warnings.warn("Unequal number of values: %d != %d" % (len(vals)/2, len(args)/2), stacklevel=3)
                # Assume lost trailing arguments are optional
                for i in range(0, min(len(args), len(vals)), 2):
                    key_a = args[i]
                    val_a = args[i+1]
                    key_b = vals[i]
                    val_b = vals[i+1]
                    equivalent(val_a, val_b, key_a, key_b)

def parse(obj):
    ans = obj
    if type(obj) == dict:
        for key in ans:
            ans[key] = parse(ans[key])
    elif isinstance(obj, sio.matlab.mio5_params.mat_struct):
        ans = {}
        for key in obj._fieldnames:
            ans[key] = parse(obj.__dict__[key])
    elif isinstance(obj,np.ndarray):
        if obj.dtype == np.dtype('O'):
            # cell-array, otherwise leave alone. Assumes 1D.
            ans = []
            for item in obj:
                ans.append(parse(item))
    return ans

def str2func(name, offset=0):
    scope = inspect.stack()[1+offset][0].f_globals
    if name in scope:
        return scope[name]
    else:
        for s in scope:
            if inspect.ismodule(scope[s]):
                # print("str2func recursing into '%s'" % s)
                for m in inspect.getmembers(scope[s]):
                    if m[0] == name:
                        return m[1]

def get_instance():
    global singleton
    if singleton == None:
        singleton = Numnum()
    return singleton

def named_args(kv):
    v = []
    for i in range(0, len(kv), 2):
        v.append(kv[i+1])
    return v

def unnamed_args(k):
    v = []
    if type(k) == np.ndarray or type(k) == list:
        for i in range(0, len(k)):
            v.append(k[i+1])
    else:
        v.append(k)
    return v

def replay(filename, mode=0):
    this       = get_instance()
    this.idxn  = 0
    this.idxu  = 0
    this.ids   = {}
    this.ctx   = []
    this.gid   = 0
    this.state = parse(sio.loadmat(filename, chars_as_strings=True, struct_as_record=False, squeeze_me=True))
    this.mode  = -1
    this.unit  = 1
    this.run   = None
    this.depth = 0

    testname = None
    if type(mode) == str:
        testname = mode
        mode     = -1

    # print(filename)

    test_results = {}

    # run integration test
    if mode == 0 or mode > 0:
        f = str2func(this.state["numnum_function"], 1)
        v = unnamed_args(this.state["numnum_varargin"])
        f(*v)
        print("integration %s: pass" % this.state["numnum_function"])

    # run unit tests
    if mode == 0 or mode < 0:
        total_tests = 0
        for key in this.state.keys():
            if testname and (testname != key):
                continue
            if not( key.startswith("numnum_") or key.startswith("_") ):
                runs = this.state[key]
                f    = str2func(key, 1)
                if f == None:
                    print('Skipping %s...\n' % key)
                    continue

                if type(runs) != list:
                    runs = [runs]

                passes = 0
                for j in range(0, len(runs)):
                    run = runs[j]
                    arg = named_args(run["arg"])
                    ret = named_args(run["ret"])

                    this.mode  = 0      # disable verification in functions...
                    this.run   = run    # ...except top-level
                    this.depth = 0
                    this.unit  = 1      # keep random generation enabled
                    this.idxn  = 0      # reset random numbers
                    this.idxu  = 0

                    try:
                        # Invoke. Return values validated internally.
                        f( *arg )
                        passes  = passes + 1
                    except Exception as e:
                        print(e.message)
                        pass
                        #raise

                    this.mode  = -1
                    this.run   = None
                    this.depth = 0

                    #total_tests = total_tests + 1
                    #try:
                    #    if len(ret) == 1:
                    #        equivalent( ret[0], results, run["ret"][0], run["ret"][0] )
                    #    else:
                    #        for k in range(0, len(ret)):
                    #            equivalent( ret[k], results[k], run["ret"][2*k], run["ret"][2*k] )
                    #    passes = passes + 1;
                    #except Exception as e:
                    #    print(e.message)
                    #    pass

                #errstr= "%s: %d%% pass (%d/%d)" % (run["name"], round(float(passes)/float(len(runs))*100.0), passes, len(runs) )
                #print(errstr)
                #if passes != len(runs):
                #    raise Exception(errstr)
                #assert passes == len(runs)

                test_results[key] = Result( key, passes, len(runs) )

        #if total_tests == 0:
        #    raise Exception("No unit tests found");
    return test_results

def record(filename, f, *args):
    this       = get_instance()
    this.idxn  = 0
    this.idxu  = 0
    this.ids   = {}
    this.ctx   = []
    this.gid   = 0
    this.state = {}
    this.mode  = 1
    this.unit  = 0
    this.run   = None
    this.depth = 0

    n = 10000
    this.state["numnum_randn"]    = np.random.standard_normal((1, n))
    this.state["numnum_rand"]     = np.random.random( (1, n) )
    this.state["numnum_function"] = "" # FIXME
    this.state["numnum_varargin"] = args

    f(*args)
    sio.savemat(filename, this.state)

def caller(offset=0):
    return inspect.stack()[2+offset][3]

def arguments(*args):
    this = get_instance()
    this.depth = this.depth + 1

    if this.mode:
        this.push()
        this.validate('arg', *args)
    elif this.run and this.depth == 1:
        this._validate(this.run['arg'], *args)

def returns(*args):
    this = get_instance()
    this.depth = this.depth - 1

    if this.mode:
        this.validate('ret', *args)
        this.pop()
    elif this.run and this.depth == 0:
        this._validate(this.run['ret'], *args)

def values(*args):
    this = get_instance()
    if this.mode:
        this.validate('val', *args)
    elif this.run and this.depth == 1:
        this._validate(this.run['val'], *args)

# Reproducible deterministic random number generation
def randn(r, c):
    this = get_instance()
    v    = np.random.standard_normal((r, c))
    if this.mode or this.unit:
        idx = 0 # needs to be deterministic for unit tests
        for i in range(0, r):
            for j in range(0, c):
                v[i,j] = this.state["numnum_randn"][ idx % this.state["numnum_randn"].shape[0] ]
                idx    = idx + 1
    return v

# Reproducible deterministic random number generation
def rand(r, c):
    this = get_instance()
    v    = np.random.random((r, c))
    if this.mode or this.unit:
        idx = 0 # needs to be deterministic for unit tests
        for i in range(0, r):
            for j in range(0, c):
                v[i,j] = this.state["numnum_rand"][ idx % this.state["numnum_rand"].shape[0] ]
                idx    = idx + 1
    return v

# Reproducible deterministic random number generation
def randperm(n):
    this = get_instance()
    v    = randperm(n)
    if this.mode or this.unit:
        # FIXME: slow and dumb...
        raise Exception('Not implemented')

# Fix handling of 1d ndarrays
def insist(v, rows, cols):
    if rows == 0 and cols == 0:
        raise Exception("Both rows and cols connot be zero")

    if type(v) == float:
        v = np.ones(shape=(1,1), dtype=np.float64) * v

    if type(v) == int:
        v = np.ones(shape=(1,1), dtype=np.float64) * float(v)

    if rows == 0:
        rows = v.size / cols
    if cols == 0:
        cols = v.size / rows

    if v.ndim == 1:
        v = v.reshape( ( rows  , cols) )

    # TODO: is this ever desirable?
    elif (v.shape[0] != v.shape[1]) and v.shape[0] == cols and v.shape[1] == rows:
        warnings.warn("Implicit use of transpose")
        v = v.T

    assert v.shape[1] == cols
    assert v.shape[0] == rows
    return v

def equivalent(a, b, A = "a", B = "b"):

    olda = a
    oldb = b

    if type(a) == type(None):
        warnings.warn("Ignoring null (return?) value for '%s'" % A)
        return

    if isinstance(a,np.bool_) and not isinstance(b,np.bool_):
        if a:
            a = 1
        else:
            a = 0

    if isinstance(a,Number):
        a = np.ones( (1,1) ).reshape((1,1)) * float(a)

    if isinstance(b,Number):
        b = np.ones( (1,1) ).reshape((1,1)) * float(b)

    if type(a) != type(b):
        # check if scalar before complaining
        if type(a) == np.ndarray and len(a.shape):
            if a.shape[0] == 1:
                if len(a.shape) == 1:
                    a0 = a[0]
                else:
                    a0 = a[0,0]
                if float(a0) == float(b):
                    return
        elif type(a) == list and type(b) == np.ndarray:
            pass
        elif isinstance(a,Number) and type(b) == np.ndarray:
            # Compare a scalar with an array: start by converting
            # a to a length-1 list
            a = [a]
        else:
            raise Exception("class(%s) = %s and class(%s) = %s" % (A, type(a), B, type(b)))

    if type(a) == np.ndarray:

        # Meh. Fix up shapes
        if len(a.shape) == 1 and len(b.shape) == 2:
            if b.shape[0] == 1:
                a = a.reshape( (1, a.shape[0]) )
            elif b.shape[1] == 1:
                a = a.reshape( (a.shape[0], 1) )

        if len(b.shape) == 1 and len(a.shape) == 2:
            if a.shape[0] == 1:
                b = b.reshape( (1, b.shape[0]) )
            elif a.shape[1] == 1:
                b = b.reshape( (b.shape[0], 1) )

        if len(a.shape) == 1 and len(b.shape) == 1:
            a = a.reshape( (a.shape[0], 1) )
            b = b.reshape( (b.shape[0], 1) )

        if b.shape[1] == 0:
            pdb.set_trace()
            b = np.ones((1,1)).resize((1,1)) * float(b)

        if a.shape != b.shape:
            raise Exception("size(%s) = %dx%d and size(%s) = %dx%d" % (A, a.shape[0], a.shape[1], B, b.shape[0], b.shape[1]))

        delta = np.abs(a-b)
        chk   = delta > 1e-6
        if chk.any():
            errstr = "%s ~= %s\n%s\n%s" % (A, B, str(a), str(b))
            raise Exception(errstr)

    elif type(a) == dict:
        for k in a.keys():
            equivalent(a[k], b[k], A = "%s.%s" % (A, k), B = "%s.%s" % (B, k))
    elif type(a) == list:
        if len(a) != len(b):
            raise Exception("len(%s) = %i and len(%s) = %i" % (A, len(a), B, len(b)))
        for i in range(0, min(len(a), len(b))):
            equivalent(a[i], b[i], A = "%s[%d]" % (A, i), B = "%s[%s]" % (B, i))
<commit_msg>Catch all exception for equivalent<commit_after>import numpy as np
import numpy.matlib
import scipy as sp
import scipy.io as sio
import inspect
import pdb
from numbers import Number

import warnings
import pdb

singleton = None

class Result:
    def __init__(this, name, passes=0, total=0):
        this.name   = name
        this.passes = float(passes)
        this.total  = float(total)

    def __iadd__(this, that):
        this.passes = this.passes + that.passes
        this.total  = this.total  + that.total
        return this

    def passed(this):
        return this.passes == this.total

    def __repr__(this):
        fr = 0.0
        if this.total > 0:
            fr = this.passes / this.total
        return "%s: %d%% pass (%d/%d)" % (this.name, round(fr*100.0), this.passes, this.total )

class Numnum:
        def __init__(this):
            this.idxn  = 0
            this.idxu  = 0
            this.ids   = {}
            this.ctx   = []
            this.gid   = 0
            this.state = {}
            this.mode  = 0
            this.unit  = 0
            this.run   = None
            this.depth = 0

        def push(this):
            """ push new context onto stack """
            name = caller(1)
            if name in this.ids:
                this.ids[name] = this.ids[name] + 1
            else:
                this.ids[name] = 1
            ctx = {}
            ctx["name"] = name
            ctx["run"]  = this.ids[name]
            this.ctx.append(ctx)

        def pop(this):
            """ pop context off of stack """
            ctx = this.ctx.pop()
            if this.mode > 0:
                if ctx["name"] not in this.state:
                    this.state[ctx["name"]] = []

                runs = this.state[ctx["name"]]

                if ctx["run"] == len(runs)+1:
                    runs.append(ctx)
                else:
                    raise Exception("wtf: %d ~ %d" % (ctx["run"] , len(runs)))
                # this.state[ctx.name] = runs

        def validate(this, str, *args):
            ctx = this.ctx[-1]

            if this.mode > 0:
                ctx[str] = args
            else:
                funs = this.state[ctx["name"]]
                if type(funs) != list:
                    funs = [funs]
                fun  = funs[ ctx["run"] - 1 ]
                vals = fun[str]
                this._validate(vals, *args)
            # this.ctx{end} = ctx;

        def _validate(this, vals, *args):
                if len(vals) != len(args):
                    warnings.warn("Unequal number of values: %d != %d" % (len(vals)/2, len(args)/2), stacklevel=3)
                # Assume lost trailing arguments are optional
                for i in range(0, min(len(args), len(vals)), 2):
                    key_a = args[i]
                    val_a = args[i+1]
                    key_b = vals[i]
                    val_b = vals[i+1]
                    equivalent(val_a, val_b, key_a, key_b)

def parse(obj):
    ans = obj
    if type(obj) == dict:
        for key in ans:
            ans[key] = parse(ans[key])
    elif isinstance(obj, sio.matlab.mio5_params.mat_struct):
        ans = {}
        for key in obj._fieldnames:
            ans[key] = parse(obj.__dict__[key])
    elif isinstance(obj,np.ndarray):
        if obj.dtype == np.dtype('O'):
            # cell-array, otherwise leave alone. Assumes 1D.
            ans = []
            for item in obj:
                ans.append(parse(item))
    return ans

def str2func(name, offset=0):
    scope = inspect.stack()[1+offset][0].f_globals
    if name in scope:
        return scope[name]
    else:
        for s in scope:
            if inspect.ismodule(scope[s]):
                # print("str2func recursing into '%s'" % s)
                for m in inspect.getmembers(scope[s]):
                    if m[0] == name:
                        return m[1]

def get_instance():
    global singleton
    if singleton == None:
        singleton = Numnum()
    return singleton

def named_args(kv):
    v = []
    for i in range(0, len(kv), 2):
        v.append(kv[i+1])
    return v

def unnamed_args(k):
    v = []
    if type(k) == np.ndarray or type(k) == list:
        for i in range(0, len(k)):
            v.append(k[i+1])
    else:
        v.append(k)
    return v

def replay(filename, mode=0):
    this       = get_instance()
    this.idxn  = 0
    this.idxu  = 0
    this.ids   = {}
    this.ctx   = []
    this.gid   = 0
    this.state = parse(sio.loadmat(filename, chars_as_strings=True, struct_as_record=False, squeeze_me=True))
    this.mode  = -1
    this.unit  = 1
    this.run   = None
    this.depth = 0

    testname = None
    if type(mode) == str:
        testname = mode
        mode     = -1

    # print(filename)

    test_results = {}

    # run integration test
    if mode == 0 or mode > 0:
        f = str2func(this.state["numnum_function"], 1)
        v = unnamed_args(this.state["numnum_varargin"])
        f(*v)
        print("integration %s: pass" % this.state["numnum_function"])

    # run unit tests
    if mode == 0 or mode < 0:
        total_tests = 0
        for key in this.state.keys():
            if testname and (testname != key):
                continue
            if not( key.startswith("numnum_") or key.startswith("_") ):
                runs = this.state[key]
                f    = str2func(key, 1)
                if f == None:
                    print('Skipping %s...\n' % key)
                    continue

                if type(runs) != list:
                    runs = [runs]

                passes = 0
                for j in range(0, len(runs)):
                    run = runs[j]
                    arg = named_args(run["arg"])
                    ret = named_args(run["ret"])

                    this.mode  = 0      # disable verification in functions...
                    this.run   = run    # ...except top-level
                    this.depth = 0
                    this.unit  = 1      # keep random generation enabled
                    this.idxn  = 0      # reset random numbers
                    this.idxu  = 0

                    try:
                        # Invoke. Return values validated internally.
                        f( *arg )
                        passes  = passes + 1
                    except Exception as e:
                        print(e.message)
                        pass
                        #raise

                    this.mode  = -1
                    this.run   = None
                    this.depth = 0

                    #total_tests = total_tests + 1
                    #try:
                    #    if len(ret) == 1:
                    #        equivalent( ret[0], results, run["ret"][0], run["ret"][0] )
                    #    else:
                    #        for k in range(0, len(ret)):
                    #            equivalent( ret[k], results[k], run["ret"][2*k], run["ret"][2*k] )
                    #    passes = passes + 1;
                    #except Exception as e:
                    #    print(e.message)
                    #    pass

                #errstr= "%s: %d%% pass (%d/%d)" % (run["name"], round(float(passes)/float(len(runs))*100.0), passes, len(runs) )
                #print(errstr)
                #if passes != len(runs):
                #    raise Exception(errstr)
                #assert passes == len(runs)

                test_results[key] = Result( key, passes, len(runs) )

        #if total_tests == 0:
        #    raise Exception("No unit tests found");
    return test_results

def record(filename, f, *args):
    this       = get_instance()
    this.idxn  = 0
    this.idxu  = 0
    this.ids   = {}
    this.ctx   = []
    this.gid   = 0
    this.state = {}
    this.mode  = 1
    this.unit  = 0
    this.run   = None
    this.depth = 0

    n = 10000
    this.state["numnum_randn"]    = np.random.standard_normal((1, n))
    this.state["numnum_rand"]     = np.random.random( (1, n) )
    this.state["numnum_function"] = "" # FIXME
    this.state["numnum_varargin"] = args

    f(*args)
    sio.savemat(filename, this.state)

def caller(offset=0):
    return inspect.stack()[2+offset][3]

def arguments(*args):
    this = get_instance()
    this.depth = this.depth + 1

    if this.mode:
        this.push()
        this.validate('arg', *args)
    elif this.run and this.depth == 1:
        this._validate(this.run['arg'], *args)

def returns(*args):
    this = get_instance()
    this.depth = this.depth - 1

    if this.mode:
        this.validate('ret', *args)
        this.pop()
    elif this.run and this.depth == 0:
        this._validate(this.run['ret'], *args)

def values(*args):
    this = get_instance()
    if this.mode:
        this.validate('val', *args)
    elif this.run and this.depth == 1:
        this._validate(this.run['val'], *args)

# Reproducible deterministic random number generation
def randn(r, c):
    this = get_instance()
    v    = np.random.standard_normal((r, c))
    if this.mode or this.unit:
        idx = 0 # needs to be deterministic for unit tests
        for i in range(0, r):
            for j in range(0, c):
                v[i,j] = this.state["numnum_randn"][ idx % this.state["numnum_randn"].shape[0] ]
                idx    = idx + 1
    return v

# Reproducible deterministic random number generation
def rand(r, c):
    this = get_instance()
    v    = np.random.random((r, c))
    if this.mode or this.unit:
        idx = 0 # needs to be deterministic for unit tests
        for i in range(0, r):
            for j in range(0, c):
                v[i,j] = this.state["numnum_rand"][ idx % this.state["numnum_rand"].shape[0] ]
                idx    = idx + 1
    return v

# Reproducible deterministic random number generation
def randperm(n):
    this = get_instance()
    v    = randperm(n)
    if this.mode or this.unit:
        # FIXME: slow and dumb...
        raise Exception('Not implemented')

# Fix handling of 1d ndarrays
def insist(v, rows, cols):
    if rows == 0 and cols == 0:
        raise Exception("Both rows and cols connot be zero")

    if type(v) == float:
        v = np.ones(shape=(1,1), dtype=np.float64) * v

    if type(v) == int:
        v = np.ones(shape=(1,1), dtype=np.float64) * float(v)

    if rows == 0:
        rows = v.size / cols
    if cols == 0:
        cols = v.size / rows

    if v.ndim == 1:
        v = v.reshape( ( rows  , cols) )

    # TODO: is this ever desirable?
    elif (v.shape[0] != v.shape[1]) and v.shape[0] == cols and v.shape[1] == rows:
        warnings.warn("Implicit use of transpose")
        v = v.T

    assert v.shape[1] == cols
    assert v.shape[0] == rows
    return v

def equivalent(a, b, A = "a", B = "b"):

    olda = a
    oldb = b

    if type(a) == type(None):
        warnings.warn("Ignoring null (return?) value for '%s'" % A)
        return

    if isinstance(a,np.bool_) and not isinstance(b,np.bool_):
        if a:
            a = 1
        else:
            a = 0

    if isinstance(a,Number):
        a = np.ones( (1,1) ).reshape((1,1)) * float(a)

    if isinstance(b,Number):
        b = np.ones( (1,1) ).reshape((1,1)) * float(b)

    if type(a) != type(b):
        # check if scalar before complaining
        if type(a) == np.ndarray and len(a.shape):
            if a.shape[0] == 1:
                if len(a.shape) == 1:
                    a0 = a[0]
                else:
                    a0 = a[0,0]
                if float(a0) == float(b):
                    return
        elif type(a) == list and type(b) == np.ndarray:
            pass
        elif isinstance(a,Number) and type(b) == np.ndarray:
            # Compare a scalar with an array: start by converting
            # a to a length-1 list
            a = [a]
        else:
            raise Exception("class(%s) = %s and class(%s) = %s" % (A, type(a), B, type(b)))

    if type(a) == np.ndarray:

        # Meh. Fix up shapes
        if len(a.shape) == 1 and len(b.shape) == 2:
            if b.shape[0] == 1:
                a = a.reshape( (1, a.shape[0]) )
            elif b.shape[1] == 1:
                a = a.reshape( (a.shape[0], 1) )

        if len(b.shape) == 1 and len(a.shape) == 2:
            if a.shape[0] == 1:
                b = b.reshape( (1, b.shape[0]) )
            elif a.shape[1] == 1:
                b = b.reshape( (b.shape[0], 1) )

        if len(a.shape) == 1 and len(b.shape) == 1:
            a = a.reshape( (a.shape[0], 1) )
            b = b.reshape( (b.shape[0], 1) )

        if b.shape[1] == 0:
            pdb.set_trace()
            b = np.ones((1,1)).resize((1,1)) * float(b)

        if a.shape != b.shape:
            raise Exception("size(%s) = %dx%d and size(%s) = %dx%d" % (A, a.shape[0], a.shape[1], B, b.shape[0], b.shape[1]))

        delta = np.abs(a-b)
        chk   = delta > 1e-6
        if chk.any():
            errstr = "%s ~= %s\n%s\n%s" % (A, B, str(a), str(b))
            raise Exception(errstr)

    elif type(a) == dict:
        for k in a.keys():
            equivalent(a[k], b[k], A = "%s.%s" % (A, k), B = "%s.%s" % (B, k))
    elif type(a) == list:
        if len(a) != len(b):
            raise Exception("len(%s) = %i and len(%s) = %i" % (A, len(a), B, len(b)))
        for i in range(0, min(len(a), len(b))):
            equivalent(a[i], b[i], A = "%s[%d]" % (A, i), B = "%s[%s]" % (B, i))

    raise Exception("Cannot check equivalence of %s (%s) and %s (%s)" % (A, type(a), B, type(b) ))
    <|endoftext|>


<commit_before>#! /usr/bin/env python

"""Further iterator tools.
"""

import itertools
from ..itertools_compat import ifilter, imap, ifilterfalse
from .. import pairs
import functools

def itercons(new_head, tail):
    """Cons a value onto the beginning of an iterator.

    Like itertools.chain([new_head], tail)

    >>> list(itercons(1, [2, 3, 4]))
    [1, 2, 3, 4]
    """
    return itertools.chain([new_head], tail)

def diverge(right_function, items):
    """Return a pair of iterators: (left, right)

    right will yield values where right_function(val) is truthy.
    left will yield values where right_function(val) is falsey.

    >>> is_odd = lambda x : (x % 2)
    >>> (evens, odds) = diverge(is_odd, [1, 2, 3, 4, 5, 6])
    >>> list(evens)
    [2, 4, 6]
    >>> list(odds)
    [1, 3, 5]
    """
    left_candidates, right_candidates = itertools.tee(items)
    left = ifilterfalse(right_function, left_candidates)
    right = ifilter(right_function, right_candidates)
    return left, right

def partition(left_function, items):
    """Like 'diverge' except the values passing left_function go into the
    left hand side of the tuple, and otherwise go into the right.

    >>> is_odd = lambda x : (x % 2)
    >>> (odds, evens) = partition(is_odd, [1, 2, 3, 4, 5, 6])
    >>> list(evens)
    [2, 4, 6]
    >>> list(odds)
    [1, 3, 5]
    """
    return pairs.swap(diverge(left_function, items))

def partition_strict(left_function, items):
    """Like 'partition' but returns two lists instead of lazy iterators.

    Should be faster than partition because it only goes through 'items' once.

    >>> is_odd = lambda x : (x % 2)
    >>> partition_strict(is_odd, [1, 2, 3, 4, 5, 6])
    ([1, 3, 5], [2, 4, 6])
    """
    left = []
    right = []
    for item in items:
        (left if left_function(item) else right).append(item)
    return (left, right)

def sift(sieves, items):
    """Progressively sift out values into a series of chunks.

    This will help getting a list of people by age range for example,
    by pulling out each age range in turn.

    The order of sieves matters.  An item will go into the first group
    whose predicate it satisfies.

    >>> from ..op import lt
    >>> sieves = [('< 10', lt(10)), ('10 <= x < 50', lt(50)), ('>= 50', sift_rest)]
    >>> sifted = list(sift(sieves, [1,2,9,10,11,10,9,11,49,50,49,100]))
    >>> len(sifted)
    3
    >>> pairs.lift_snd(list)(sifted[0])
    ('< 10', [1, 2, 9, 9])
    >>> pairs.lift_snd(list)(sifted[1])
    ('10 <= x < 50', [10, 11, 10, 11, 49, 49])
    >>> pairs.lift_snd(list)(sifted[2])
    ('>= 50', [50, 100])
    """
    return _sift(sieves, items, partition_fun=partition)

def sift_strict(sieves, items):
    """Strict version of 'sift' - you get [(label, list)] instead of
    [(label, iterator)].

    Profiling suggests that this is slightly faster when len(sieves) == 2,
    but the greater the number of sieves, the bigger the advantage of using
    sift_strict over sift.

    Here I sift with just two levels (low and gargantuan):
        devbox% python profilem.py
        Test it does what we want...
        Partition to high and low 1 lots of 1000000 numbers...
        0.57293009758
        Partition strictly to high and low 1 lots of 1000000 numbers...
        0.493767023087

    And then I adjust my script to have six levels (low, med, high, huge,
    massive, gargantuan):

        Test it does what we want...
        Partition to high and low 1 lots of 1000000 numbers...
        1.74753117561
        Partition strictly to high and low 1 lots of 1000000 numbers...
        1.38616394997

    Note the much more marked difference between the two figures - add
    a little more than 0.1 of a second for each extra sieve.

    If you're going to run this repeatedly over a million numbers, the
    improvements will soon stack up.

    >>> from ..op import lt
    >>> sieves = [('< 10', lt(10)), ('10 <= x < 50', lt(50)), ('>= 50', sift_rest)]
    >>> sifted = list(sift_strict(sieves, [1,2,9,10,11,10,9,11,49,50,49,100]))
    >>> len(sifted)
    3
    >>> sifted[0]
    ('< 10', [1, 2, 9, 9])
    >>> sifted[1]
    ('10 <= x < 50', [10, 11, 10, 11, 49, 49])
    >>> sifted[2]
    ('>= 50', [50, 100])
    """
    # The only implementation difference between this and
    # sift is the partition function used.
    return _sift(sieves, items, partition_fun=partition_strict)

def _sift(sieves, items, partition_fun):
    rest = items
    for (label, predicate) in sieves:
        (matching, rest) = partition_fun(predicate, rest)
        yield (label, matching)

def sift_rest(x):
    """Predicate to consume the rest of an sequence in a sift operaton.

    >>> [(x, list(y)) for (x,y) in sift([('catchall', sift_rest)], range(6))]
    [('catchall', [0, 1, 2, 3, 4, 5])]
    """
    return True

def imap_c(func):
    """imap_c(func)(iterable) = itertools.imap(func, iterable)

    (a -> b) -> iter[a] -> iter[b]

    >>> list(imap_c(int)(['1', '2', '3']))
    [1, 2, 3]
    """
    return functools.partial(imap, func)

def ifilter_c(func):
    """ifilter_c(func)(iterable) = itertools.ifilter(func, iterable)

    (a -> bool) -> iter[a] -> iter[a]

    >>> list(ifilter_c(lambda x: x % 2 == 0)([1, 2, 3, 4]))
    [2, 4]
    """
    return functools.partial(ifilter, func)

def concat(iterables):
    """Return iterables concatenated into one iterable.

    >>> list(concat([[1, 2, 3], [4, 5, 6]]))
    [1, 2, 3, 4, 5, 6]
    """
    return itertools.chain(*iterables)

def concat_map(f, xs):
    """Map function f over an iterable xs and concatenate the results.

    This is useful if you want to return a variable number of items
    into your output list from your input list.

    For example you may be building a list of arguments for a program
    that takes the same option multiple times with a different
    argument each time:

    >>> dash_a_option = lambda x: ['-a', x]
    >>> list(concat_map(dash_a_option, ['a', 'b', 'c']))
    ['-a', 'a', '-a', 'b', '-a', 'c']
    """
    return concat(imap(f, xs))

def at_least(number, iterator):
    """Return whether at least number items in iterator are truthy.

    This consumes the iterator lazily, returning True as soon as the count
    hits the given number.  So in some cases it will be quicker than
    len(list(iterator)) >= number

    >>> at_least(2, [False, 3, None, ''])
    False
    >>> at_least(2, [False, 3, None, 'something'])
    True

    It's really designed for use with generator expressions:
    >>> at_least(2, (x > 10 for x in range(11)))
    False
    >>> at_least(2, (x > 10 for x in range(13)))
    True
    """
    count = 0
    for item in iterator:
        if item:
            count += 1
        if count >= number:
            return True
    return False

def at_most(number, iterator):
    """Return whether at most number items in iterator are truthy.

    This consumes the iterator lazily, returning False as soon
    as the count exceeds the given number.

    >>> at_most(2, [False, 3, None, ''])
    True
    >>> at_most(2, [False, 3, True, 'something'])
    False

    It's really designed for use with generator expressions:
    >>> at_most(2, (x > 10 for x in range(13)))
    True
    >>> at_most(2, (x > 10 for x in range(14)))
    False
    """
    count = 0
    for item in iterator:
        if item:
            count += 1
        if count > number:
            return False
    return True

if __name__ == "__main__":
    import doctest
    doctest.testmod()
<commit_msg>Deprecate diverge in favour of partition.<commit_after>#! /usr/bin/env python

"""Further iterator tools.
"""

import itertools
from ..itertools_compat import ifilter, imap, ifilterfalse
from .. import pairs
import functools
import warnings

def itercons(new_head, tail):
    """Cons a value onto the beginning of an iterator.

    Like itertools.chain([new_head], tail)

    >>> list(itercons(1, [2, 3, 4]))
    [1, 2, 3, 4]
    """
    return itertools.chain([new_head], tail)

def diverge(right_function, items):
    """Return a pair of iterators: (left, right)

    right will yield values where right_function(val) is truthy.
    left will yield values where right_function(val) is falsey.

    >>> is_odd = lambda x : (x % 2)
    >>> (evens, odds) = diverge(is_odd, [1, 2, 3, 4, 5, 6])
    >>> list(evens)
    [2, 4, 6]
    >>> list(odds)
    [1, 3, 5]
    """
    warnings.warn(DeprecationWarning(
        "'diverge' deprecated, consider using 'partition' instead"
    ))
    left_candidates, right_candidates = itertools.tee(items)
    left = ifilterfalse(right_function, left_candidates)
    right = ifilter(right_function, right_candidates)
    return left, right

def partition(left_function, items):
    """Like 'diverge' except the values passing left_function go into the
    left hand side of the tuple, and otherwise go into the right.

    >>> is_odd = lambda x : (x % 2)
    >>> (odds, evens) = partition(is_odd, [1, 2, 3, 4, 5, 6])
    >>> list(evens)
    [2, 4, 6]
    >>> list(odds)
    [1, 3, 5]
    """
    return pairs.swap(diverge(left_function, items))

def partition_strict(left_function, items):
    """Like 'partition' but returns two lists instead of lazy iterators.

    Should be faster than partition because it only goes through 'items' once.

    >>> is_odd = lambda x : (x % 2)
    >>> partition_strict(is_odd, [1, 2, 3, 4, 5, 6])
    ([1, 3, 5], [2, 4, 6])
    """
    left = []
    right = []
    for item in items:
        (left if left_function(item) else right).append(item)
    return (left, right)

def sift(sieves, items):
    """Progressively sift out values into a series of chunks.

    This will help getting a list of people by age range for example,
    by pulling out each age range in turn.

    The order of sieves matters.  An item will go into the first group
    whose predicate it satisfies.

    >>> from ..op import lt
    >>> sieves = [('< 10', lt(10)), ('10 <= x < 50', lt(50)), ('>= 50', sift_rest)]
    >>> sifted = list(sift(sieves, [1,2,9,10,11,10,9,11,49,50,49,100]))
    >>> len(sifted)
    3
    >>> pairs.lift_snd(list)(sifted[0])
    ('< 10', [1, 2, 9, 9])
    >>> pairs.lift_snd(list)(sifted[1])
    ('10 <= x < 50', [10, 11, 10, 11, 49, 49])
    >>> pairs.lift_snd(list)(sifted[2])
    ('>= 50', [50, 100])
    """
    return _sift(sieves, items, partition_fun=partition)

def sift_strict(sieves, items):
    """Strict version of 'sift' - you get [(label, list)] instead of
    [(label, iterator)].

    Profiling suggests that this is slightly faster when len(sieves) == 2,
    but the greater the number of sieves, the bigger the advantage of using
    sift_strict over sift.

    Here I sift with just two levels (low and gargantuan):
        devbox% python profilem.py
        Test it does what we want...
        Partition to high and low 1 lots of 1000000 numbers...
        0.57293009758
        Partition strictly to high and low 1 lots of 1000000 numbers...
        0.493767023087

    And then I adjust my script to have six levels (low, med, high, huge,
    massive, gargantuan):

        Test it does what we want...
        Partition to high and low 1 lots of 1000000 numbers...
        1.74753117561
        Partition strictly to high and low 1 lots of 1000000 numbers...
        1.38616394997

    Note the much more marked difference between the two figures - add
    a little more than 0.1 of a second for each extra sieve.

    If you're going to run this repeatedly over a million numbers, the
    improvements will soon stack up.

    >>> from ..op import lt
    >>> sieves = [('< 10', lt(10)), ('10 <= x < 50', lt(50)), ('>= 50', sift_rest)]
    >>> sifted = list(sift_strict(sieves, [1,2,9,10,11,10,9,11,49,50,49,100]))
    >>> len(sifted)
    3
    >>> sifted[0]
    ('< 10', [1, 2, 9, 9])
    >>> sifted[1]
    ('10 <= x < 50', [10, 11, 10, 11, 49, 49])
    >>> sifted[2]
    ('>= 50', [50, 100])
    """
    # The only implementation difference between this and
    # sift is the partition function used.
    return _sift(sieves, items, partition_fun=partition_strict)

def _sift(sieves, items, partition_fun):
    rest = items
    for (label, predicate) in sieves:
        (matching, rest) = partition_fun(predicate, rest)
        yield (label, matching)

def sift_rest(x):
    """Predicate to consume the rest of an sequence in a sift operaton.

    >>> [(x, list(y)) for (x,y) in sift([('catchall', sift_rest)], range(6))]
    [('catchall', [0, 1, 2, 3, 4, 5])]
    """
    return True

def imap_c(func):
    """imap_c(func)(iterable) = itertools.imap(func, iterable)

    (a -> b) -> iter[a] -> iter[b]

    >>> list(imap_c(int)(['1', '2', '3']))
    [1, 2, 3]
    """
    return functools.partial(imap, func)

def ifilter_c(func):
    """ifilter_c(func)(iterable) = itertools.ifilter(func, iterable)

    (a -> bool) -> iter[a] -> iter[a]

    >>> list(ifilter_c(lambda x: x % 2 == 0)([1, 2, 3, 4]))
    [2, 4]
    """
    return functools.partial(ifilter, func)

def concat(iterables):
    """Return iterables concatenated into one iterable.

    >>> list(concat([[1, 2, 3], [4, 5, 6]]))
    [1, 2, 3, 4, 5, 6]
    """
    return itertools.chain(*iterables)

def concat_map(f, xs):
    """Map function f over an iterable xs and concatenate the results.

    This is useful if you want to return a variable number of items
    into your output list from your input list.

    For example you may be building a list of arguments for a program
    that takes the same option multiple times with a different
    argument each time:

    >>> dash_a_option = lambda x: ['-a', x]
    >>> list(concat_map(dash_a_option, ['a', 'b', 'c']))
    ['-a', 'a', '-a', 'b', '-a', 'c']
    """
    return concat(imap(f, xs))

def at_least(number, iterator):
    """Return whether at least number items in iterator are truthy.

    This consumes the iterator lazily, returning True as soon as the count
    hits the given number.  So in some cases it will be quicker than
    len(list(iterator)) >= number

    >>> at_least(2, [False, 3, None, ''])
    False
    >>> at_least(2, [False, 3, None, 'something'])
    True

    It's really designed for use with generator expressions:
    >>> at_least(2, (x > 10 for x in range(11)))
    False
    >>> at_least(2, (x > 10 for x in range(13)))
    True
    """
    count = 0
    for item in iterator:
        if item:
            count += 1
        if count >= number:
            return True
    return False

def at_most(number, iterator):
    """Return whether at most number items in iterator are truthy.

    This consumes the iterator lazily, returning False as soon
    as the count exceeds the given number.

    >>> at_most(2, [False, 3, None, ''])
    True
    >>> at_most(2, [False, 3, True, 'something'])
    False

    It's really designed for use with generator expressions:
    >>> at_most(2, (x > 10 for x in range(13)))
    True
    >>> at_most(2, (x > 10 for x in range(14)))
    False
    """
    count = 0
    for item in iterator:
        if item:
            count += 1
        if count > number:
            return False
    return True

if __name__ == "__main__":
    import doctest
    doctest.testmod()
<|endoftext|>


<commit_before>import os
import sys
import base64
import random
import getpass
import datetime

__all__ = ["Log", "register"]

RED = 31
GREEN = 32
YELLOW = 33
BLUE = 34
MAGENTA = 35
CYAN = 36
WHITE = 37
WORDLIST = "/usr/share/dict/words"

def colorize(text, color, bold):
    if color:
        boldizer = "1;" if bold else ""
        start_color = "\033[%s%dm" % (boldizer, color)
        end_color = "\033[0m"
        return "".join((start_color, text, end_color))
    else:
        return text

def get_random_word():
    file_size = os.path.getsize(WORDLIST)
    word = ""

    with open(WORDLIST, "r") as wordlist:
        while not word.isalpha() or not word.islower() or len(word) < 5:
            position = random.randint(1, file_size)
            wordlist.seek(position)
            wordlist.readline()
            word = wordlist.readline().rstrip("\n")

    return word

class Log(object):
    def __init__(self, config, args):
        self.args = args

        # generate a unique id for the push
        self.push_id = get_random_word()

        # build the path for the logfile
        timestamp = datetime.datetime.utcnow().strftime("%Y-%m-%d_%H:%M:%S")
        log_name = "-".join((timestamp, self.push_id)) + ".log"
        self.log_path = os.path.join(config.paths.log_root, log_name)

        # open the logfile
        self.logfile = open(self.log_path, "w")

    def write(self, text, color=None, bold=False, newline=False, stdout=True):
        suffix = "\n" if newline else ""
        self.logfile.write(text + suffix)
        if stdout:
            sys.stdout.write(colorize(text, color, bold) + suffix)
        self.flush()

    def flush(self):
        self.logfile.flush()
        sys.stdout.flush()

    def debug(self, message, *args):
        self.write(message % args,
                   newline=True,
                   color=GREEN,
                   stdout=not self.args.quiet)

    def info(self, message, *args):
        self.write(message % args,
                   newline=True,
                   stdout=not self.args.quiet)

    def notice(self, message, *args):
        self.write(message % args,
                   newline=True,
                   color=BLUE,
                   bold=True,
                   stdout=not self.args.quiet)

    def warning(self, message, *args):
        self.write(message % args,
                   newline=True,
                   color=YELLOW,
                   bold=True)

    def critical(self, message, *args):
        self.write(message % args,
                   newline=True,
                   color=RED,
                   bold=True)

    def close(self):
        self.logfile.close()

def register(config, args, deployer, log):
    @deployer.push_began
    def on_push_began(deployer):
        user = getpass.getuser()
        time = datetime.datetime.utcnow().strftime("%Y-%m-%d %H:%M")
        args = " ".join(sys.argv[1:])
        log.write("Push started by %s at %s "
                  "UTC with args: %s" % (user, time, args),
                  newline=True, stdout=False)
<commit_msg>Remove unused import in log.py<commit_after>import os
import sys
import random
import getpass
import datetime

__all__ = ["Log", "register"]

RED = 31
GREEN = 32
YELLOW = 33
BLUE = 34
MAGENTA = 35
CYAN = 36
WHITE = 37
WORDLIST = "/usr/share/dict/words"

def colorize(text, color, bold):
    if color:
        boldizer = "1;" if bold else ""
        start_color = "\033[%s%dm" % (boldizer, color)
        end_color = "\033[0m"
        return "".join((start_color, text, end_color))
    else:
        return text

def get_random_word():
    file_size = os.path.getsize(WORDLIST)
    word = ""

    with open(WORDLIST, "r") as wordlist:
        while not word.isalpha() or not word.islower() or len(word) < 5:
            position = random.randint(1, file_size)
            wordlist.seek(position)
            wordlist.readline()
            word = wordlist.readline().rstrip("\n")

    return word

class Log(object):
    def __init__(self, config, args):
        self.args = args

        # generate a unique id for the push
        self.push_id = get_random_word()

        # build the path for the logfile
        timestamp = datetime.datetime.utcnow().strftime("%Y-%m-%d_%H:%M:%S")
        log_name = "-".join((timestamp, self.push_id)) + ".log"
        self.log_path = os.path.join(config.paths.log_root, log_name)

        # open the logfile
        self.logfile = open(self.log_path, "w")

    def write(self, text, color=None, bold=False, newline=False, stdout=True):
        suffix = "\n" if newline else ""
        self.logfile.write(text + suffix)
        if stdout:
            sys.stdout.write(colorize(text, color, bold) + suffix)
        self.flush()

    def flush(self):
        self.logfile.flush()
        sys.stdout.flush()

    def debug(self, message, *args):
        self.write(message % args,
                   newline=True,
                   color=GREEN,
                   stdout=not self.args.quiet)

    def info(self, message, *args):
        self.write(message % args,
                   newline=True,
                   stdout=not self.args.quiet)

    def notice(self, message, *args):
        self.write(message % args,
                   newline=True,
                   color=BLUE,
                   bold=True,
                   stdout=not self.args.quiet)

    def warning(self, message, *args):
        self.write(message % args,
                   newline=True,
                   color=YELLOW,
                   bold=True)

    def critical(self, message, *args):
        self.write(message % args,
                   newline=True,
                   color=RED,
                   bold=True)

    def close(self):
        self.logfile.close()

def register(config, args, deployer, log):
    @deployer.push_began
    def on_push_began(deployer):
        user = getpass.getuser()
        time = datetime.datetime.utcnow().strftime("%Y-%m-%d %H:%M")
        args = " ".join(sys.argv[1:])
        log.write("Push started by %s at %s "
                  "UTC with args: %s" % (user, time, args),
                  newline=True, stdout=False)
<|endoftext|>


<commit_before>#!/usr/bin/env python

# Static Routes http://stackoverflow.com/questions/10486224/bottle-static-files

from bottle import route, static_file, debug, run, get, view, redirect
from bottle import post, request, response
import os, inspect, json

#enable bottle debug
debug(True)

# WebApp route path
routePath = '/pyWebMOC'
# get directory of WebApp (pyWebMOC.py's dir)
rootPath = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))

@route(routePath)
def rootHome():
    return redirect(routePath+'/index.html')

@view(routePath + '/index.html')
def home():
    return static_file("index.html", root=rootPath)

@route(routePath + '/<filename:re:.*\.html>')
def html_file(filename):
    return static_file(filename, root=rootPath)

@get(routePath + '/assets/<filepath:path>')
def assets_file(filepath):
    return static_file(filepath, root=rootPath+'/assets')

#http://gotofritz.net/blog/weekly-challenge/restful-python-api-bottle/
"""
POST action
curl -i -X GET http://localhost:8080/pyWebMOC/jsonGET

GET action
curl -X POST -H "Content-Type: application/json" -d '{"id":"1","name":"OopsMonk"}' http://localhost:8080/pyWebMOC/jsonPOST
"""
@get(routePath + '/json')
def testJsonGET():
    print dict(request.headers)
    return {"id":1,"name":"Sam"}

@post(routePath + '/json')
def testJsonPost():
    #print dict(request.headers)
    data = request.json
    print data
    if data == None:
        return json.dumps({'Status':"Failed!"})
    else:
        return json.dumps({'Status':"Success!"})

@get(routePath + '/gettest')
def gettest():
    return "get test return!!!\n"

run(host='localhost', port=8080, reloader=True)

<commit_msg>add function list.<commit_after>#!/usr/bin/env python

# Static Routes http://stackoverflow.com/questions/10486224/bottle-static-files

from bottle import route, static_file, debug, run, get, view, redirect
from bottle import post, request, response
import os, inspect, json
import moc

#enable bottle debug
debug(True)

# WebApp route path
routePath = '/pyWebMOC'
# get directory of WebApp (pyWebMOC.py's dir)
rootPath = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))

@route(routePath)
def rootHome():
    return redirect(routePath+'/index.html')

@view(routePath + '/index.html')
def home():
    return static_file("index.html", root=rootPath)

@route(routePath + '/<filename:re:.*\.html>')
def html_file(filename):
    return static_file(filename, root=rootPath)

@get(routePath + '/assets/<filepath:path>')
def assets_file(filepath):
    return static_file(filepath, root=rootPath+'/assets')

"""
Function list
* Player control GET
    * return moc server state (play/stop/pause/not running)

* Player control POST
    * Previous
    * Play / Resume
    * Next
    * Pause
    * Stop
    * volume

* Player info
    * Song name
    * current time
    * duration
    *
"""

#control GET API return
@get(routePath + '/ctl')
def MOCControlGET():
    """
    -1: moc server not running
    0: Stopping
    1: Pause
    2: Playing
    """
    st = moc.get_state()
    print "Get moc server status : %d" % st
    return json.dumps({'Status':st})

#handle control post action
def CtlHandle(data):
    """
    request:
    {'do':action}
    action:
    0: Prev
    1: Play/Pause
    2: Next
    3: Stop
    4: Volume
    5: Add playlist
    6: append playlist
    7: clear playlist
    8:
    response:
    {'ack': error}
    error:
    0: Success
    not zero: Failed.
    """

    return json.dumps({'ack':0})

#control POST API
@post(routePath + '/ctl')
def MOCControlPOST():
    data = request.json
    if data == None:
        return json.dumps({'ack': -1})

    print "Get cmd : %s" % data
    return CtlHandle(data)

#http://gotofritz.net/blog/weekly-challenge/restful-python-api-bottle/
"""
POST action
curl -i -X GET http://localhost:8080/pyWebMOC/jsonGET

GET action
curl -X POST -H "Content-Type: application/json" -d '{"id":"1","name":"OopsMonk"}' http://localhost:8080/pyWebMOC/jsonPOST
"""
@get(routePath + '/json')
def testJsonGET():
    print dict(request.headers)
    return {"id":1,"name":"Sam"}

@post(routePath + '/json')
def testJsonPost():
    #print dict(request.headers)
    data = request.json
    print data
    if data == None:
        return json.dumps({'Status':"Failed!"})
    else:
        return json.dumps({'Status':"Success!"})

@get(routePath + '/gettest')
def gettest():
    return "get test return!!!\n"

run(host='localhost', port=8080, reloader=True)

<|endoftext|>


<commit_before># -*- coding: utf-8 -*-

import unittest
from datetime import datetime

import pandas as pd
from mock import patch
from pandas.util.testing import assert_frame_equal

from WindAdapter.api import factor_load
from WindAdapter.enums import OutputFormat

class MockWindData(object):
    def __init__(self, data, codes, error_code, fields, times):
        self.Data = data
        self.Codes = codes
        self.ErrorCode = error_code
        self.Fields = fields
        self.Times = times

class TestApi(unittest.TestCase):
    @patch('WindAdapter.data_provider.WindDataProvider.query_data')
    def testFactorLoad_case1(self, mock_query_data):
        start_date = '2016-01-01'
        end_date = '2016-02-01'
        factor_name = 'PB'
        sec_id = ['000001.SZ', '000002.SZ', '000003.SZ']

        mock_data = MockWindData(data=[[1, 3, 5]],
                                 codes=sec_id,
                                 error_code=0,
                                 fields=['PB'],
                                 times=[datetime(2016, 1, 1),
                                        datetime(2016, 2, 1)])
        mock_query_data.return_value = mock_data

        calculated = factor_load(start_date=start_date,
                                 end_date=end_date,
                                 factor_name=factor_name,
                                 sec_id=sec_id,
                                 output_data_format=OutputFormat.MULTI_INDEX_DF,
                                 is_index=False)

        expected = pd.DataFrame(data=[1, 3, 5, 1, 3, 5],
                                index=pd.MultiIndex.from_product([['2016-01-29', '2016-02-01'],
                                                                  ['000001.SZ', '000002.SZ', '000003.SZ']],
                                                                 names=['date', 'secID']),
                                columns=['factor'])
        assert_frame_equal(calculated, expected)

        calculated = factor_load(start_date=start_date,
                                 end_date=end_date,
                                 factor_name=factor_name,
                                 sec_id=sec_id,
                                 output_data_format=OutputFormat.PITVOT_TABLE_DF,
                                 is_index=False)
        expected = pd.DataFrame(data=[[1, 3, 5], [1, 3, 5]],
                                columns=['000001.SZ', '000002.SZ', '000003.SZ'],
                                index=['2016-01-29', '2016-02-01'])
        assert_frame_equal(calculated, expected)

    @patch('WindAdapter.data_provider.WindDataProvider.query_data')
    @patch('WindAdapter.data_provider.WindDataProvider.biz_days_list')
    @patch('WindAdapter.data_provider.WindDataProvider.advance_date')
    def testFactorLoad_case2(self, mock_adv_date, mock_days_list, mock_query_data):
        start_date = '2016-01-01'
        end_date = '2016-02-01'
        factor_name = 'STDQ'
        sec_id = ['000001.SZ', '000002.SZ', '000003.SZ', '000004.SZ']

        mock_data = MockWindData(data=[[1, 2, 3, 4]],
                                 codes=sec_id,
                                 error_code=0,
                                 fields=['STDQ'],
                                 times=[datetime(2016, 1, 1)])
        mock_query_data.return_value = mock_data
        mock_days_list.return_value = [datetime(2016, 1, 1), datetime(2016, 2, 1)]
        mock_adv_date.return_value = datetime(2015, 9, 1)

        calculated = factor_load(start_date=start_date,
                                 end_date=end_date,
                                 factor_name=factor_name,
                                 sec_id=sec_id,
                                 tenor='1Q',
                                 output_data_format=OutputFormat.MULTI_INDEX_DF,
                                 is_index=False)
        expected = pd.DataFrame(data=[1, 2, 3, 4, 1, 2, 3, 4],
                                index=pd.MultiIndex.from_product([['2016-01-01', '2016-02-01'],
                                                                  ['000001.SZ', '000002.SZ', '000003.SZ',
                                                                   '000004.SZ']],
                                                                 names=['date', 'secID']),
                                columns=['factor'])
        assert_frame_equal(calculated, expected)

        calculated = factor_load(start_date=start_date,
                                 end_date=end_date,
                                 factor_name=factor_name,
                                 sec_id=sec_id,
                                 tenor='1Q',
                                 output_data_format=OutputFormat.PITVOT_TABLE_DF,
                                 is_index=False)
        expected = pd.DataFrame(data=[[1, 2, 3, 4], [1, 2, 3, 4]],
                                index=['2016-01-01', '2016-02-01'],
                                columns=['000001.SZ', '000002.SZ', '000003.SZ', '000004.SZ'])
        assert_frame_equal(calculated, expected)
<commit_msg>Fix build - py3 issue<commit_after># -*- coding: utf-8 -*-

import unittest
from datetime import datetime
import pandas as pd
try:
    from unittest.mock import patch
except ImportError:
    from mock import patch
from pandas.util.testing import assert_frame_equal

from WindAdapter.api import factor_load
from WindAdapter.enums import OutputFormat

class MockWindData(object):
    def __init__(self, data, codes, error_code, fields, times):
        self.Data = data
        self.Codes = codes
        self.ErrorCode = error_code
        self.Fields = fields
        self.Times = times

class TestApi(unittest.TestCase):
    @patch('WindAdapter.data_provider.WindDataProvider.query_data')
    def testFactorLoad_case1(self, mock_query_data):
        start_date = '2016-01-01'
        end_date = '2016-02-01'
        factor_name = 'PB'
        sec_id = ['000001.SZ', '000002.SZ', '000003.SZ']

        mock_data = MockWindData(data=[[1, 3, 5]],
                                 codes=sec_id,
                                 error_code=0,
                                 fields=['PB'],
                                 times=[datetime(2016, 1, 1),
                                        datetime(2016, 2, 1)])
        mock_query_data.return_value = mock_data

        calculated = factor_load(start_date=start_date,
                                 end_date=end_date,
                                 factor_name=factor_name,
                                 sec_id=sec_id,
                                 output_data_format=OutputFormat.MULTI_INDEX_DF,
                                 is_index=False)

        expected = pd.DataFrame(data=[1, 3, 5, 1, 3, 5],
                                index=pd.MultiIndex.from_product([['2016-01-29', '2016-02-01'],
                                                                  ['000001.SZ', '000002.SZ', '000003.SZ']],
                                                                 names=['date', 'secID']),
                                columns=['factor'])
        assert_frame_equal(calculated, expected)

        calculated = factor_load(start_date=start_date,
                                 end_date=end_date,
                                 factor_name=factor_name,
                                 sec_id=sec_id,
                                 output_data_format=OutputFormat.PITVOT_TABLE_DF,
                                 is_index=False)
        expected = pd.DataFrame(data=[[1, 3, 5], [1, 3, 5]],
                                columns=['000001.SZ', '000002.SZ', '000003.SZ'],
                                index=['2016-01-29', '2016-02-01'])
        assert_frame_equal(calculated, expected)

    @patch('WindAdapter.data_provider.WindDataProvider.query_data')
    @patch('WindAdapter.data_provider.WindDataProvider.biz_days_list')
    @patch('WindAdapter.data_provider.WindDataProvider.advance_date')
    def testFactorLoad_case2(self, mock_adv_date, mock_days_list, mock_query_data):
        start_date = '2016-01-01'
        end_date = '2016-02-01'
        factor_name = 'STDQ'
        sec_id = ['000001.SZ', '000002.SZ', '000003.SZ', '000004.SZ']

        mock_data = MockWindData(data=[[1, 2, 3, 4]],
                                 codes=sec_id,
                                 error_code=0,
                                 fields=['STDQ'],
                                 times=[datetime(2016, 1, 1)])
        mock_query_data.return_value = mock_data
        mock_days_list.return_value = [datetime(2016, 1, 1), datetime(2016, 2, 1)]
        mock_adv_date.return_value = datetime(2015, 9, 1)

        calculated = factor_load(start_date=start_date,
                                 end_date=end_date,
                                 factor_name=factor_name,
                                 sec_id=sec_id,
                                 tenor='1Q',
                                 output_data_format=OutputFormat.MULTI_INDEX_DF,
                                 is_index=False)
        expected = pd.DataFrame(data=[1, 2, 3, 4, 1, 2, 3, 4],
                                index=pd.MultiIndex.from_product([['2016-01-01', '2016-02-01'],
                                                                  ['000001.SZ', '000002.SZ', '000003.SZ',
                                                                   '000004.SZ']],
                                                                 names=['date', 'secID']),
                                columns=['factor'])
        assert_frame_equal(calculated, expected)

        calculated = factor_load(start_date=start_date,
                                 end_date=end_date,
                                 factor_name=factor_name,
                                 sec_id=sec_id,
                                 tenor='1Q',
                                 output_data_format=OutputFormat.PITVOT_TABLE_DF,
                                 is_index=False)
        expected = pd.DataFrame(data=[[1, 2, 3, 4], [1, 2, 3, 4]],
                                index=['2016-01-01', '2016-02-01'],
                                columns=['000001.SZ', '000002.SZ', '000003.SZ', '000004.SZ'])
        assert_frame_equal(calculated, expected)
<|endoftext|>


<commit_before>from datetime import datetime, timedelta
import logging
import math
import re

from babel import Locale

from sqlalchemy import Table, Column, ForeignKey, func, or_
from sqlalchemy import DateTime, Integer, Float, Boolean, Unicode, UnicodeText
from sqlalchemy.orm import reconstructor

import meta

log = logging.getLogger(__name__)

instance_table = Table(
    'instance', meta.data,
    Column('id', Integer, primary_key=True),
    Column('key', Unicode(20), nullable=False, unique=True),
    Column('label', Unicode(255), nullable=False),
    Column('description', UnicodeText(), nullable=True),
    Column('required_majority', Float, nullable=False),
    Column('activation_delay', Integer, nullable=False),
    Column('create_time', DateTime, default=func.now()),
    Column('access_time', DateTime, default=func.now(),
           onupdate=func.now()),
    Column('delete_time', DateTime, nullable=True),
    Column('creator_id', Integer, ForeignKey('user.id'),
           nullable=False),
    Column('default_group_id', Integer, ForeignKey('group.id'),
           nullable=True),
    Column('allow_adopt', Boolean, default=True),
    Column('allow_delegate', Boolean, default=True),
    Column('allow_propose', Boolean, default=True),
    Column('allow_index', Boolean, default=True),
    Column('hidden', Boolean, default=False),
    Column('locale', Unicode(7), nullable=True),
    Column('css', UnicodeText(), nullable=True),
    Column('frozen', Boolean, default=False),
    Column('milestones', Boolean, default=False),
    Column('use_norms', Boolean, nullable=True, default=True),
    Column('require_selection', Boolean, nullable=True, default=False),
    Column('is_authenticated', Boolean, nullable=True, default=False),
    Column('hide_global_categories', Boolean, nullable=True, default=False),
    Column('editable_comments_default', Boolean, nullable=True, default=True),
    Column('require_valid_email', Boolean, nullable=True, default=True),
)

# Instance is not a delegateable - but it should - or you cannot do
# instance wide delegation

class Instance(meta.Indexable):
    __tablename__ = 'instance'

    INSTANCE_KEY = re.compile("^[a-zA-Z][a-zA-Z0-9-]{2,18}$")

    def __init__(self, key, label, creator, description=None):
        self.key = key
        self.label = label
        self.creator = creator
        self.description = description
        self.required_majority = 0.66
        self.activation_delay = 7
        self.allow_adopt = True
        self.allow_delegate = True
        self.allow_propose = True
        self.allow_index = True
        self.hidden = False
        self.frozen = False
        self.require_selection = False
        self._required_participation = None

    @reconstructor
    def _reconstruct(self):
        self._required_participation = None

    def _get_locale(self):
        if not self._locale:
            return None
        return Locale.parse(self._locale)

    def _set_locale(self, locale):
        self._locale = unicode(locale)

    locale = property(_get_locale, _set_locale)

    def current_memberships(self):
        return [m for m in self.memberships if not m.is_expired()]

    def members(self):
        '''
        return all users that are members of this instance through
        global or local membership
        '''
        from adhocracy.model.permission import Permission
        members = [membership.user for membership in
                   self.current_memberships()]
        global_membership = Permission.find('global.member')
        for group in global_membership.groups:
            for membership in group.memberships:
                if membership.instance == None and not membership.expire_time:
                    members.append(membership.user)
        return list(set(members))

    def _get_required_participation(self):
        if self._required_participation is None:
            from adhocracy.lib.democracy import Decision
            avg = Decision.average_decisions(self)
            required = int(math.ceil(max(2, avg * self.required_majority)))
            self._required_participation = required
        return self._required_participation

    required_participation = property(_get_required_participation)

    def _get_activation_timedelta(self):
        return timedelta(days=self.activation_delay)
        #return timedelta(minutes=self.activation_delay)

    activation_timedelta = property(_get_activation_timedelta)

    def _get_num_proposals(self):
        from proposal import Proposal
        q = meta.Session.query(Proposal)
        q = q.filter(Proposal.instance == self)
        q = q.filter(or_(Proposal.delete_time == None,
                         Proposal.delete_time >= datetime.utcnow()))
        return q.count()

    num_proposals = property(_get_num_proposals)

    def _get_num_members(self):
        from membership import Membership
        q = meta.Session.query(Membership)
        q = q.filter(Membership.instance == self)
        q = q.filter(or_(Membership.expire_time == None,
                         Membership.expire_time >= datetime.utcnow()))
        return q.count()

    num_members = property(_get_num_members)

    @classmethod
    #@meta.session_cached
    def find(cls, key, instance_filter=True, include_deleted=False):
        key = unicode(key).lower()
        try:
            q = meta.Session.query(Instance)
            try:
                q = q.filter(Instance.id == int(key))
            except ValueError:
                q = q.filter(Instance.key == unicode(key))
            if not include_deleted:
                q = q.filter(or_(Instance.delete_time == None,
                                 Instance.delete_time > datetime.utcnow()))
            return q.limit(1).first()
        except Exception, e:
            log.warn("find(%s): %s" % (key, e))
            return None

    def is_deleted(self, at_time=None):
        if at_time is None:
            at_time = datetime.utcnow()
        return (self.delete_time is not None) and \
            self.delete_time <= at_time

    def delete(self, delete_time=None):
        if delete_time is None:
            delete_time = datetime.utcnow()
        for delegateable in self.delegateables:
            delegateable.delete(delete_time)
        for membership in self.memberships:
            membership.expire(delete_time)
        if not self.is_deleted(delete_time):
            self.delete_time = delete_time

    def is_shown(self, at_time=None):
        if at_time is None:
            at_time = datetime.utcnow()
        return not (self.is_deleted(at_time) or self.hidden)

    _index_id_attr = 'key'

    @classmethod
    def all_q(cls):
        return meta.Session.query(Instance)

    @classmethod
    def all(cls, limit=None, include_deleted=False, include_hidden=False):
        q = cls.all_q()
        q = meta.Session.query(Instance)
        if not include_deleted:
            q = q.filter(or_(Instance.delete_time == None,
                             Instance.delete_time > datetime.utcnow()))
        if not include_hidden:
            q = q.filter(or_(Instance.hidden == None,
                             Instance.hidden == False))
        if limit is not None:
            q = q.limit(limit)
        return q.all()

    @classmethod
    def create(cls, key, label, user, description=None, locale=None):
        from group import Group
        from membership import Membership
        from page import Page

        instance = Instance(unicode(key).lower(), label, user)
        instance.description = description
        instance.default_group = Group.by_code(Group.INSTANCE_DEFAULT)
        if locale is not None:
            instance.locale = locale
        meta.Session.add(instance)
        supervisor_group = Group.by_code(Group.CODE_SUPERVISOR)
        membership = Membership(user, instance, supervisor_group,
                                approved=True)
        meta.Session.add(membership)
        Page.create(instance, label, u"", user)
        meta.Session.flush()
        return instance

    def to_dict(self):
        from adhocracy.lib import helpers as h
        d = dict(id=self.id,
                 key=self.key,
                 label=self.label,
                 creator=self.creator.user_name,
                 required_majority=self.required_majority,
                 activation_delay=self.activation_delay,
                 allow_adopt=self.allow_adopt,
                 allow_delegate=self.allow_delegate,
                 allow_propose=self.allow_propose,
                 allow_index=self.allow_index,
                 hidden=self.hidden,
                 url=h.entity_url(self),
                 instance_url=h.instance.url(self),
                 default_group=self.default_group.code,
                 create_time=self.create_time)
        if self.description:
            d['description'] = self.description
        return d

    def to_index(self):
        from adhocracy.lib.event import stats as estats
        index = super(Instance, self).to_index()
        if self.hidden:
            index['skip'] = True
        index.update(dict(
            instance=self.key,
            title=self.label,
            tags=[],
            body=self.description,
            user=self.creator.user_name,
            activity=estats.instance_activity(self)
        ))
        return index

    def __repr__(self):
        return u"<Instance(%d,%s)>" % (self.id, self.key)
<commit_msg>autojoin: Let all users join a created instance automatically (Fixes #247, hhucn/adhocracy.hhu_theme#130)<commit_after>from datetime import datetime, timedelta
import logging
import math
import re

from babel import Locale

from pylons import config

from sqlalchemy import Table, Column, ForeignKey, func, or_
from sqlalchemy import DateTime, Integer, Float, Boolean, Unicode, UnicodeText
from sqlalchemy.orm import reconstructor

import adhocracy.model
from adhocracy.model import meta

log = logging.getLogger(__name__)

instance_table = Table(
    'instance', meta.data,
    Column('id', Integer, primary_key=True),
    Column('key', Unicode(20), nullable=False, unique=True),
    Column('label', Unicode(255), nullable=False),
    Column('description', UnicodeText(), nullable=True),
    Column('required_majority', Float, nullable=False),
    Column('activation_delay', Integer, nullable=False),
    Column('create_time', DateTime, default=func.now()),
    Column('access_time', DateTime, default=func.now(),
           onupdate=func.now()),
    Column('delete_time', DateTime, nullable=True),
    Column('creator_id', Integer, ForeignKey('user.id'),
           nullable=False),
    Column('default_group_id', Integer, ForeignKey('group.id'),
           nullable=True),
    Column('allow_adopt', Boolean, default=True),
    Column('allow_delegate', Boolean, default=True),
    Column('allow_propose', Boolean, default=True),
    Column('allow_index', Boolean, default=True),
    Column('hidden', Boolean, default=False),
    Column('locale', Unicode(7), nullable=True),
    Column('css', UnicodeText(), nullable=True),
    Column('frozen', Boolean, default=False),
    Column('milestones', Boolean, default=False),
    Column('use_norms', Boolean, nullable=True, default=True),
    Column('require_selection', Boolean, nullable=True, default=False),
    Column('is_authenticated', Boolean, nullable=True, default=False),
    Column('hide_global_categories', Boolean, nullable=True, default=False),
    Column('editable_comments_default', Boolean, nullable=True, default=True),
    Column('require_valid_email', Boolean, nullable=True, default=True),
)

# Instance is not a delegateable - but it should - or you cannot do
# instance wide delegation

class Instance(meta.Indexable):
    __tablename__ = 'instance'

    INSTANCE_KEY = re.compile("^[a-zA-Z][a-zA-Z0-9-]{2,18}$")

    def __init__(self, key, label, creator, description=None):
        self.key = key
        self.label = label
        self.creator = creator
        self.description = description
        self.required_majority = 0.66
        self.activation_delay = 7
        self.allow_adopt = True
        self.allow_delegate = True
        self.allow_propose = True
        self.allow_index = True
        self.hidden = False
        self.frozen = False
        self.require_selection = False
        self._required_participation = None

    @reconstructor
    def _reconstruct(self):
        self._required_participation = None

    def _get_locale(self):
        if not self._locale:
            return None
        return Locale.parse(self._locale)

    def _set_locale(self, locale):
        self._locale = unicode(locale)

    locale = property(_get_locale, _set_locale)

    def current_memberships(self):
        return [m for m in self.memberships if not m.is_expired()]

    def members(self):
        '''
        return all users that are members of this instance through
        global or local membership
        '''
        from adhocracy.model.permission import Permission
        members = [membership.user for membership in
                   self.current_memberships()]
        global_membership = Permission.find('global.member')
        for group in global_membership.groups:
            for membership in group.memberships:
                if membership.instance == None and not membership.expire_time:
                    members.append(membership.user)
        return list(set(members))

    def _get_required_participation(self):
        if self._required_participation is None:
            from adhocracy.lib.democracy import Decision
            avg = Decision.average_decisions(self)
            required = int(math.ceil(max(2, avg * self.required_majority)))
            self._required_participation = required
        return self._required_participation

    required_participation = property(_get_required_participation)

    def _get_activation_timedelta(self):
        return timedelta(days=self.activation_delay)
        #return timedelta(minutes=self.activation_delay)

    activation_timedelta = property(_get_activation_timedelta)

    def _get_num_proposals(self):
        from proposal import Proposal
        q = meta.Session.query(Proposal)
        q = q.filter(Proposal.instance == self)
        q = q.filter(or_(Proposal.delete_time == None,
                         Proposal.delete_time >= datetime.utcnow()))
        return q.count()

    num_proposals = property(_get_num_proposals)

    def _get_num_members(self):
        from membership import Membership
        q = meta.Session.query(Membership)
        q = q.filter(Membership.instance == self)
        q = q.filter(or_(Membership.expire_time == None,
                         Membership.expire_time >= datetime.utcnow()))
        return q.count()

    num_members = property(_get_num_members)

    @classmethod
    #@meta.session_cached
    def find(cls, key, instance_filter=True, include_deleted=False):
        key = unicode(key).lower()
        try:
            q = meta.Session.query(Instance)
            try:
                q = q.filter(Instance.id == int(key))
            except ValueError:
                q = q.filter(Instance.key == unicode(key))
            if not include_deleted:
                q = q.filter(or_(Instance.delete_time == None,
                                 Instance.delete_time > datetime.utcnow()))
            return q.limit(1).first()
        except Exception, e:
            log.warn("find(%s): %s" % (key, e))
            return None

    def is_deleted(self, at_time=None):
        if at_time is None:
            at_time = datetime.utcnow()
        return (self.delete_time is not None) and \
            self.delete_time <= at_time

    def delete(self, delete_time=None):
        if delete_time is None:
            delete_time = datetime.utcnow()
        for delegateable in self.delegateables:
            delegateable.delete(delete_time)
        for membership in self.memberships:
            membership.expire(delete_time)
        if not self.is_deleted(delete_time):
            self.delete_time = delete_time

    def is_shown(self, at_time=None):
        if at_time is None:
            at_time = datetime.utcnow()
        return not (self.is_deleted(at_time) or self.hidden)

    _index_id_attr = 'key'

    @classmethod
    def all_q(cls):
        return meta.Session.query(Instance)

    @classmethod
    def all(cls, limit=None, include_deleted=False, include_hidden=False):
        q = cls.all_q()
        q = meta.Session.query(Instance)
        if not include_deleted:
            q = q.filter(or_(Instance.delete_time == None,
                             Instance.delete_time > datetime.utcnow()))
        if not include_hidden:
            q = q.filter(or_(Instance.hidden == None,
                             Instance.hidden == False))
        if limit is not None:
            q = q.limit(limit)
        return q.all()

    @classmethod
    def create(cls, key, label, user, description=None, locale=None):
        from group import Group
        from membership import Membership
        from page import Page

        instance = Instance(unicode(key).lower(), label, user)
        instance.description = description
        instance.default_group = Group.by_code(Group.INSTANCE_DEFAULT)
        if locale is not None:
            instance.locale = locale
        meta.Session.add(instance)
        supervisor_group = Group.by_code(Group.CODE_SUPERVISOR)
        membership = Membership(user, instance, supervisor_group,
                                approved=True)
        meta.Session.add(membership)
        Page.create(instance, label, u"", user)

        # Autojoin the user in instances
        config_autojoin = config.get('adhocracy.instances.autojoin')
        if (config_autojoin and
                (config_autojoin == 'ALL' or
                key in (k.strip() for k in config_autojoin.split(',')))):
            users = adhocracy.model.User.all()
            for u in users:
                autojoin_membership = Membership(u, instance,
                                                 instance.default_group)
                meta.Session.add(autojoin_membership)

        meta.Session.flush()
        return instance

    def to_dict(self):
        from adhocracy.lib import helpers as h
        d = dict(id=self.id,
                 key=self.key,
                 label=self.label,
                 creator=self.creator.user_name,
                 required_majority=self.required_majority,
                 activation_delay=self.activation_delay,
                 allow_adopt=self.allow_adopt,
                 allow_delegate=self.allow_delegate,
                 allow_propose=self.allow_propose,
                 allow_index=self.allow_index,
                 hidden=self.hidden,
                 url=h.entity_url(self),
                 instance_url=h.instance.url(self),
                 default_group=self.default_group.code,
                 create_time=self.create_time)
        if self.description:
            d['description'] = self.description
        return d

    def to_index(self):
        from adhocracy.lib.event import stats as estats
        index = super(Instance, self).to_index()
        if self.hidden:
            index['skip'] = True
        index.update(dict(
            instance=self.key,
            title=self.label,
            tags=[],
            body=self.description,
            user=self.creator.user_name,
            activity=estats.instance_activity(self)
        ))
        return index

    def __repr__(self):
        return u"<Instance(%d,%s)>" % (self.id, self.key)
<|endoftext|>