<commit_before>from __future__ import division, print_function
import numpy as np
import os
import time
from sys import stdout

def output2file(string2output,
                filename=os.getcwd()+'tempfile_from_output2file',
                mode=None):
    if mode is None:
        raise Exception(
            "Please give a mode argument when calling this function "
            "(use mode='w' to overwrite file or mode='a' to append to file)."
        )

    with open(filename, mode) as fout:
        fout.write(string2output)

def n_choose_k(n, k):
    from math import factorial
    return factorial(n) / factorial(k) / factorial(n - k)

def curvature(func, tval, dt=0.01, num_pts_2use=100):
    n = num_pts_2use // 2
    ts = [tval + k * dt for k in range(-n, n)]
    a = np.array([[func(t).real, func(t).imag] for t in ts])
    dx_dt = np.gradient(a[:, 0])
    dy_dt = np.gradient(a[:, 1])
    d2x_dt2 = np.gradient(dx_dt)
    d2y_dt2 = np.gradient(dy_dt)

    denom = (dx_dt * dx_dt + dy_dt * dy_dt) ** 1.5
    curvature = np.abs(d2x_dt2 * dy_dt - dx_dt * d2y_dt2) / denom
    return curvature[n]

def printvars(*vargs):
    """prints a pasteable "var = var" to paste into your code

    Args:
        *vargs: variable names as strings

    Returns:
        None
    """
    for varname in vargs:
        print("print('%s = ' + str(%s))" % (varname, varname))

def nparray2nestedlist(npa):  # 2d arrays only
    return [list(row) for row in npa]

def format001(digits, num):
    if digits < len(str(num)):
        raise Exception("digits<len(str(num))")
    return '0' * (digits - len(str(num))) + str(num)

def format__1(digits, num):
    if digits < len(str(num)):
        raise Exception("digits<len(str(num))")
    return ' ' * (digits - len(str(num))) + str(num)

def printmat(arr, row_labels=[], col_labels=[]):  # pretty print a matrix (nested list or 2d numpy array)
    try:
        flattenList(arr)
    except TypeError:
        arr = [[x] for x in arr]  # adds support for vectors
    finally:
        max_chars = max([len(str(item)) for item in flattenList(
            arr) + col_labels])  # the maximum number of chars required to display any item in list
    if row_labels == [] and col_labels == []:
        for row in arr:
            print('[%s]' % (' '.join(format__1(max_chars, i) for i in row)))
    elif row_labels != [] and col_labels != []:
        rw = max([len(str(item)) for item in row_labels])  # max char width of row__labels
        print('%s %s' % (' ' * (rw + 1), ' '.join(format__1(max_chars, i) for i in col_labels)))
        for row_label, row in zip(row_labels, arr):
            print('%s [%s]' % (format__1(rw, row_label), ' '.join(format__1(max_chars, i) for i in row)))
    else:
        raise Exception(
            "This case is not implemented...either both row_labels and col_labels must be given or neither.")

def eucdist_numpy(l1, l2):  # takes in two lists (or tuples) and returns the euclidian distance between them
    from numpy import array
    from numpy.linalg import norm
    return norm(array(list(l1)) - array(list(l2)))

def eucnorm_numpy(lon):
    from numpy import array
    from numpy.linalg import norm
    return norm(array(list(lon)))

def eucnormalize_numpy(lon):
    from numpy import array
    from numpy.linalg import norm
    lona = array(list(lon))
    return list(lona / norm(lona))

class Radius(object):
    def __init__(self, origin):
        self.origin = origin

    def __repr__(self):
        return '<Radius object for measuring distance from origin = %s>' % self.origin

    def of(self, pt):
        return abs(pt - self.origin)

def eucdot(l1, l2):
    assert len(l1) == len(l2)
    return sum((l1[i] * l2[i] for i in range(len(l1))))

def bool2bin(boolval):  # this can also be done by using True.real
    if boolval:
        return 1
    else:
        return 0

def plotPoints(points):
    import matplotlib.pyplot as plt
    fig = plt.figure()
    ax = fig.add_subplot(111)
    x_points = [z.real for z in points]
    y_points = [z.imag for z in points]
    ax.plot(x_points, y_points, 'b')
    ax.set_xlabel('x-points')
    ax.set_ylabel('y-points')
    ax.set_title('Simple XY point plot')
    fig.show()

def format_time(et):
    if et < 60:
        return '%.1f sec' % et
    elif et < 3600:
        return '%.1f min' % (et / 60)
    else:
        return '%.1f hrs' % (et / 3600)

class Timer(object):
    def __init__(self, name='', overwrite=False, formatted=True):
        self.name = name
        self.overwrite = overwrite
        self.formatted = formatted
        if self.name:
            if overwrite:
                stdout.write('\r[%s] Running... ' % self.name)
            else:
                stdout.write('[%s] Running... ' % self.name)

    def __enter__(self):
        self.tstart = time.time()

    def __exit__(self, type, value, traceback):
        elapsed_time = time.time() - self.tstart
        if self.formatted:
            stdout.write('Done (in %s)' % format_time(elapsed_time))
        else:
            stdout.write('Done (in %s seconds)' % elapsed_time)
        stdout.write('' if self.overwrite else '\n')
        return

def memoize(f):
    """ Memoization decorator for functions taking one or more arguments."""

    class MemoDict(dict):
        def __init__(self, f_):
            self.f = f_

        def __call__(self, *args):
            return self[args]

        def __missing__(self, key):
            ret = self[key] = self.f(*key)
            return ret

    return MemoDict(f)

def ignoreCase(*something_to_say):
    try:
        input = raw_input
    except NameError:
        pass
    dec = input("Press 'i' to ignore or 'r' to remember (or 'exit' to exit): ")
    if dec == 'i':
        return True
    elif dec == 'r':
        return False
    elif dec == 'exit':
        raise Exception("User-forced exit.")
    else:
        ignoreCase(something_to_say)

def inputyn():
    try:
        input = raw_input
    except NameError:
        pass
    dec = input("Enter 'y' or 'n' (or 'e' to exit): ")
    if dec == 'y':
        return True
    elif dec == 'n':
        return False
    elif dec == 'e':
        raise Exception("User-forced exit.")
    else:
        inputyn()

def ask_user(options=None):
    """options should be input as dict whose entries are descriptions.
    Note: q is used (by default) for manual termination."""
    if not options:
        return inputyn()
    try:
        input = raw_input
    except NameError:
        pass
    print("Enter one of the following options.")
    for key in options.keys():
        print(key, ":", dict[key])
    if not options.haskey('q'):
        print("q : exit this menu")
    dec = input()
    print("")

    if options.haskey(dec):
        return dec
    elif dec == 'q':
        raise Exception("User-forced exit.")
    else:
        ask_user()

class boolset(list):
    def __contains__(self, element):
        for x in self:
            if x == element:
                return True
        return False

    def booladd(self, element):
        if element not in self:
            self.append(element)

class ConditionalPrint(object):
    def __init__(self, b):
        self.b = b

    def __repr__(self):
        return str(self.b)

    def __call__(self, s, *nr):
        self.dprint(s, *nr)

    def dprint(self, s, *nr):
        if self.b:
            if nr == ('nr',):
                from sys import stdout
                stdout.write(s)  # does not end the line after printing.
            else:
                print(s)

def flattenList(list_2_flatten):
    return [item for sublist in list_2_flatten for item in sublist]

def open_in_browser(file_location):
    """Attempt to open file_location in the default web browser."""
    # if just the name of the file was given, check if it's in the Current Working Directory.
    if not os.path.isfile(file_location):
        file_location = os.path.join(os.getcwd(), file_location)
    if not os.path.isfile(file_location):
        raise IOError("\n\nFile not found.")
    try:
        import webbrowser
        new = 2  # open in a new tab, if possible
        webbrowser.get().open(file_location, new=new)

    except ImportError:
        from warnings import warn
        mes = "\nUnable to import webbrowser module.  disvg() fuction will be unable to open created \
              svg files in web browser automatically.\n"
        warn(mes)

class _Getch:  # Gets a single character from standard input.  Does not echo to the screen. (from: https://stackoverflow.com/questions/510357/python-read-a-single-character-from-the-user)
    def __init__(self):
        try:
            self.impl = _GetchWindows()
        except ImportError:
            self.impl = _GetchUnix()

    def __call__(self):
        return self.impl()

class _GetchUnix:
    def __init__(self):
        import tty, sys

    def __call__(self):
        import sys, tty, termios
        fd = sys.stdin.fileno()
        old_settings = termios.tcgetattr(fd)
        try:
            tty.setraw(sys.stdin.fileno())
            ch = sys.stdin.read(1)
        finally:
            termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
        return ch

class _GetchWindows:
    def __init__(self):
        import msvcrt

    def __call__(self):
        import msvcrt
        return msvcrt.getch()

getch = _Getch()

def createOrderingMatrix(list_of_objects, cmp_fcn, test_symmetry=False):
    """creates directed graph describing ordering."""
    from numpy import zeros
    res = zeros((len(list_of_objects), len(list_of_objects)))
    for i in range(len(list_of_objects)):
        # this should always be symmetric, so to speed up could just
        # use range(i+1:len(list_of_objects))
        for j in range(i + 1, len(list_of_objects)):
            res[i, j] = cmp_fcn(list_of_objects[i], list_of_objects[j])
            res[j, i] = -res[i, j]

    if test_symmetry:
        for i in range(len(list_of_objects)):
            for j in range(i + 1, len(list_of_objects)):
                resji = cmp_fcn(list_of_objects[j], list_of_objects[i])
                if res[i, j] != -resji:
                    raise Exception(
                        "Contradiction given by comparison_function: "
                        "cmp[%s,%s]!=-cmp[%s,%s]" % (i, j, j, i))
    return res

def createDependencyDictionary(ordering_matrix):
    """create dictionary of dependencies for toposort"""
    dep_dict = dict()
    for i in range(len(ordering_matrix)):
        dep_dict.update({i: {j for j in range(len(ordering_matrix))
                             if ordering_matrix[i][j] > 0}})
    return dep_dict

def topo_sorted(list_of_objects, cmp_fcn, test_symmetry=False,
                ordering_matrix=None):
    """easy-to-use version of toposort"""
    from toposort import toposort
    if ordering_matrix is None:
        ordering_matrix = createOrderingMatrix(
            list_of_objects, cmp_fcn, test_symmetry=test_symmetry)
    dep_dict = createDependencyDictionary(ordering_matrix)
    return toposort(dep_dict)

def limit(func, t0, side=0, epsilon=1e-16, delta0=0.5, maxits=10000, n=5):
    """computes the limit of func(t) as t->t0
    Note: The domain of func is assumed to be (t0-delta0,t0),(t0,t0+delta0), or
        the union of these intervals depending on side
    Note: the function will possibly be evaluated n*maxits times
    INPUT:
    side - determines whether right (side>0) or left (side<0); two sided if 0
    delta0 is the initial delta
    """
    from random import uniform
    assert epsilon > 0 and delta0 > 0 and maxits > 0

    if side > 0:
        delta = float(delta0)
    elif side < 0:
        delta = -float(delta0)
    else:
        posres = limit(func, t0, side=1, epsilon=epsilon, maxits=maxits, delta0=delta0)
        negres = limit(func, t0, side=-1, epsilon=epsilon, maxits=maxits, delta0=delta0)
        if abs(posres - negres) <= 2 * epsilon:
            return (posres + negres) / 2
        else:
            raise Exception("\n%s = the left side limit != the right "
                            "side limit = %s." % (negres, posres))
    lim = epsilon * 10
    old_lim = -epsilon * 10
    its = 0
    for its in range(maxits):
        if not abs(lim - old_lim) >= epsilon:
            break
        old_lim = lim
        ts = [uniform(t0, t0 + delta) for _ in range(n)]
        lims = map(func, ts)
        lim = sum(lims) / len(lims)
        delta /= n
    if its >= maxits - 1:
        raise Exception("Maximum iterations reached.")
    return lim
<commit_msg>cleanup<commit_after>from __future__ import division, print_function
import numpy as np
import os
import time
from sys import stdout

def output2file(string2output,
                filename=os.getcwd()+'tempfile_from_output2file',
                mode=None):
    if mode is None:
        raise Exception(
            "Please give a mode argument when calling this function "
            "(use mode='w' to overwrite file or mode='a' to append to file)."
        )

    with open(filename, mode) as fout:
        fout.write(string2output)

def n_choose_k(n, k):
    from math import factorial
    return factorial(n) / factorial(k) / factorial(n - k)

def curvature(func, tval, dt=0.01, num_pts_2use=100):
    n = num_pts_2use // 2
    ts = [tval + k * dt for k in range(-n, n)]
    a = np.array([[func(t).real, func(t).imag] for t in ts])
    dx_dt = np.gradient(a[:, 0])
    dy_dt = np.gradient(a[:, 1])
    d2x_dt2 = np.gradient(dx_dt)
    d2y_dt2 = np.gradient(dy_dt)

    denom = (dx_dt * dx_dt + dy_dt * dy_dt) ** 1.5
    curvature = np.abs(d2x_dt2 * dy_dt - dx_dt * d2y_dt2) / denom
    return curvature[n]

def printvars(*vargs):
    """prints a pasteable "var = var" to paste into your code

    Args:
        *vargs: variable names as strings

    Returns:
        None
    """
    for varname in vargs:
        print("print('%s = ' + str(%s))" % (varname, varname))

def nparray2nestedlist(npa):  # 2d arrays only
    return [list(row) for row in npa]

def format001(digits, num):
    if digits < len(str(num)):
        raise Exception("digits<len(str(num))")
    return '0' * (digits - len(str(num))) + str(num)

def format__1(digits, num):
    if digits < len(str(num)):
        raise Exception("digits<len(str(num))")
    return ' ' * (digits - len(str(num))) + str(num)

def printmat(arr, row_labels=[], col_labels=[]):
    """pretty print a matrix (nested list or 2d numpy array)"""
    try:
        flattenList(arr)
    except TypeError:
        arr = [[x] for x in arr]  # adds support for vectors
    finally:
        # the maximum number of chars required to display any item in list
        max_chars = \
            max([len(str(item)) for item in flattenList(arr) + col_labels])

    if row_labels == [] and col_labels == []:
        for row in arr:
            print('[%s]' % (' '.join(format__1(max_chars, i) for i in row)))
    elif row_labels != [] and col_labels != []:

        # max char width of row__labels
        rw = max([len(str(item)) for item in row_labels])

        print('%s %s' % (' ' * (rw + 1),
                         ' '.join(format__1(max_chars, i) for i in col_labels)))
        for row_label, row in zip(row_labels, arr):
            print('%s [%s]' % (format__1(rw, row_label),
                               ' '.join(format__1(max_chars, i) for i in row)))
    else:
        raise Exception("This case is not implemented...either both "
                        "row_labels and col_labels must be given or neither.")

def eucdist_numpy(l1, l2):
    """euclidian distance between two lists"""
    from numpy import array
    from numpy.linalg import norm
    return norm(array(list(l1)) - array(list(l2)))

def eucnorm_numpy(lon):
    from numpy import array
    from numpy.linalg import norm
    return norm(array(list(lon)))

def eucnormalize_numpy(lon):
    from numpy import array
    from numpy.linalg import norm
    lona = array(list(lon))
    return list(lona / norm(lona))

class Radius(object):
    def __init__(self, origin):
        self.origin = origin

    def __repr__(self):
        return '<Radius object for measuring distance from origin = %s>' % self.origin

    def of(self, pt):
        return abs(pt - self.origin)

def eucdot(l1, l2):
    assert len(l1) == len(l2)
    return sum((l1[i] * l2[i] for i in range(len(l1))))

def bool2bin(boolval):  # this can also be done by using True.real
    if boolval:
        return 1
    else:
        return 0

def plotPoints(points):
    import matplotlib.pyplot as plt
    fig = plt.figure()
    ax = fig.add_subplot(111)
    x_points = [z.real for z in points]
    y_points = [z.imag for z in points]
    ax.plot(x_points, y_points, 'b')
    ax.set_xlabel('x-points')
    ax.set_ylabel('y-points')
    ax.set_title('Simple XY point plot')
    fig.show()

def format_time(et):
    if et < 60:
        return '%.1f sec' % et
    elif et < 3600:
        return '%.1f min' % (et / 60)
    else:
        return '%.1f hrs' % (et / 3600)

class Timer(object):
    def __init__(self, name='', overwrite=False, formatted=True):
        self.name = name
        self.overwrite = overwrite
        self.formatted = formatted
        if self.name:
            if overwrite:
                stdout.write('\r[%s] Running... ' % self.name)
            else:
                stdout.write('[%s] Running... ' % self.name)

    def __enter__(self):
        self.tstart = time.time()

    def __exit__(self, type, value, traceback):
        elapsed_time = time.time() - self.tstart
        if self.formatted:
            stdout.write('Done (in %s)' % format_time(elapsed_time))
        else:
            stdout.write('Done (in %s seconds)' % elapsed_time)
        stdout.write('' if self.overwrite else '\n')
        return

def memoize(f):
    """ Memoization decorator for functions taking one or more arguments."""

    class MemoDict(dict):
        def __init__(self, f_):
            self.f = f_

        def __call__(self, *args):
            return self[args]

        def __missing__(self, key):
            ret = self[key] = self.f(*key)
            return ret

    return MemoDict(f)

def ignoreCase(*something_to_say):
    try:
        input = raw_input
    except NameError:
        pass
    dec = input("Press 'i' to ignore or 'r' to remember (or 'exit' to exit): ")
    if dec == 'i':
        return True
    elif dec == 'r':
        return False
    elif dec == 'exit':
        raise Exception("User-forced exit.")
    else:
        ignoreCase(something_to_say)

def inputyn():
    try:
        input = raw_input
    except NameError:
        pass
    dec = input("Enter 'y' or 'n' (or 'e' to exit): ")
    if dec == 'y':
        return True
    elif dec == 'n':
        return False
    elif dec == 'e':
        raise Exception("User-forced exit.")
    else:
        inputyn()

def ask_user(options=None):
    """options should be input as dict whose entries are descriptions.
    Note: q is used (by default) for manual termination."""
    if not options:
        return inputyn()
    try:
        input = raw_input
    except NameError:
        pass
    print("Enter one of the following options.")
    for key in options.keys():
        print(key, ":", dict[key])
    if not options.haskey('q'):
        print("q : exit this menu")
    dec = input()
    print("")

    if options.haskey(dec):
        return dec
    elif dec == 'q':
        raise Exception("User-forced exit.")
    else:
        ask_user()

class boolset(list):
    def __contains__(self, element):
        for x in self:
            if x == element:
                return True
        return False

    def booladd(self, element):
        if element not in self:
            self.append(element)

class ConditionalPrint(object):
    def __init__(self, b):
        self.b = b

    def __repr__(self):
        return str(self.b)

    def __call__(self, s, *nr):
        self.dprint(s, *nr)

    def dprint(self, s, *nr):
        if self.b:
            if nr == ('nr',):
                from sys import stdout
                stdout.write(s)  # does not end the line after printing.
            else:
                print(s)

def flattenList(list_2_flatten):
    return [item for sublist in list_2_flatten for item in sublist]

def open_in_browser(file_location):
    """Attempt to open file_location in the default web browser."""
    # if just the name of the file was given, check if it's in the Current Working Directory.
    if not os.path.isfile(file_location):
        file_location = os.path.join(os.getcwd(), file_location)
    if not os.path.isfile(file_location):
        raise IOError("\n\nFile not found.")
    try:
        import webbrowser
        new = 2  # open in a new tab, if possible
        webbrowser.get().open(file_location, new=new)

    except ImportError:
        from warnings import warn
        mes = "\nUnable to import webbrowser module.  disvg() fuction will be unable to open created \
              svg files in web browser automatically.\n"
        warn(mes)

class _Getch:
    """Gets a single character from standard input.

    Does not echo to the screen.

    Credit: stackoverflow.com/questions/510357
    """
    def __init__(self):
        try:
            self.impl = _GetchWindows()
        except ImportError:
            self.impl = _GetchUnix()

    def __call__(self):
        return self.impl()

class _GetchUnix:
    def __init__(self):
        import tty, sys

    def __call__(self):
        import sys, tty, termios
        fd = sys.stdin.fileno()
        old_settings = termios.tcgetattr(fd)
        try:
            tty.setraw(sys.stdin.fileno())
            ch = sys.stdin.read(1)
        finally:
            termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
        return ch

class _GetchWindows:
    def __init__(self):
        import msvcrt

    def __call__(self):
        import msvcrt
        return msvcrt.getch()

getch = _Getch()

def createOrderingMatrix(list_of_objects, cmp_fcn, test_symmetry=False):
    """creates directed graph describing ordering."""
    from numpy import zeros
    res = zeros((len(list_of_objects), len(list_of_objects)))
    for i in range(len(list_of_objects)):
        # this should always be symmetric, so to speed up could just
        # use range(i+1:len(list_of_objects))
        for j in range(i + 1, len(list_of_objects)):
            res[i, j] = cmp_fcn(list_of_objects[i], list_of_objects[j])
            res[j, i] = -res[i, j]

    if test_symmetry:
        for i in range(len(list_of_objects)):
            for j in range(i + 1, len(list_of_objects)):
                resji = cmp_fcn(list_of_objects[j], list_of_objects[i])
                if res[i, j] != -resji:
                    raise Exception(
                        "Contradiction given by comparison_function: "
                        "cmp[%s,%s]!=-cmp[%s,%s]" % (i, j, j, i))
    return res

def createDependencyDictionary(ordering_matrix):
    """create dictionary of dependencies for toposort"""
    dep_dict = dict()
    for i in range(len(ordering_matrix)):
        dep_dict.update({i: {j for j in range(len(ordering_matrix))
                             if ordering_matrix[i][j] > 0}})
    return dep_dict

def topo_sorted(list_of_objects, cmp_fcn, test_symmetry=False,
                ordering_matrix=None):
    """easy-to-use version of toposort"""
    from toposort import toposort
    if ordering_matrix is None:
        ordering_matrix = createOrderingMatrix(
            list_of_objects, cmp_fcn, test_symmetry=test_symmetry)
    dep_dict = createDependencyDictionary(ordering_matrix)
    return toposort(dep_dict)

def limit(func, t0, side=0, epsilon=1e-16, delta0=0.5, maxits=10000, n=5):
    """computes the limit of func(t) as t->t0

    Note: The domain of func is assumed to be (t0-delta0,t0),(t0,t0+delta0), or
        the union of these intervals depending on side
    Note: the function will possibly be evaluated n*maxits times

    Args:
        side: determines whether
            right (side > 0) or left (side < 0) or two-sided (side == 0)
        delta0: is the initial delta

    """
    from random import uniform
    assert epsilon > 0 and delta0 > 0 and maxits > 0

    if side > 0:
        delta = float(delta0)
    elif side < 0:
        delta = -float(delta0)
    else:
        posres = limit(
            func, t0, side=1, epsilon=epsilon, maxits=maxits, delta0=delta0)
        negres = limit(
            func, t0, side=-1, epsilon=epsilon, maxits=maxits, delta0=delta0)

        if abs(posres - negres) <= 2 * epsilon:
            return (posres + negres) / 2
        else:
            raise Exception("\n%s = the left side limit != the right "
                            "side limit = %s." % (negres, posres))
    lim = epsilon * 10
    old_lim = -epsilon * 10
    its = 0
    for its in range(maxits):
        if not abs(lim - old_lim) >= epsilon:
            break
        old_lim = lim
        ts = [uniform(t0, t0 + delta) for _ in range(n)]
        lims = map(func, ts)
        lim = sum(lims) / len(lims)
        delta /= n
    if its >= maxits - 1:
        raise Exception("Maximum iterations reached.")
    return lim
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
##############################################################################
#
#    Copyright (C) 2009 EduSense BV (<http://www.edusense.nl>).
#              (C) 2011 - 2013 Therp BV (<http://therp.nl>).
#
#    All other contributions are (C) by their respective contributors
#
#    All Rights Reserved
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as
#    published by the Free Software Foundation, either version 3 of the
#    License, or (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################

from openerp.osv import orm, fields
from openerp.tools.translate import _
from openerp import netsvc

class payment_order(orm.Model):
    '''
    Enable extra states for payment exports
    '''
    _inherit = 'payment.order'

    _columns = {
        'date_scheduled': fields.date(
            'Scheduled date if fixed',
            states={
                'sent': [('readonly', True)],
                'rejected': [('readonly', True)],
                'done': [('readonly', True)]
            },
            help='Select a date if you have chosen Preferred Date to be fixed.'
        ),
        'reference': fields.char(
            'Reference', size=128, required=True,
            states={
                'sent': [('readonly', True)],
                'rejected': [('readonly', True)],
                'done': [('readonly', True)]
            },
        ),
        'mode': fields.many2one(
            'payment.mode', 'Payment mode', select=True, required=True,
            states={
                'sent': [('readonly', True)],
                'rejected': [('readonly', True)],
                'done': [('readonly', True)]
            },
            help='Select the Payment Mode to be applied.',
        ),
        'state': fields.selection([
            ('draft', 'Draft'),
            ('open','Confirmed'),
            ('cancel','Cancelled'),
            ('sent', 'Sent'),
            ('rejected', 'Rejected'),
            ('done','Done'),
            ], 'State', select=True
        ),
        'line_ids': fields.one2many(
            'payment.line', 'order_id', 'Payment lines',
            states={
                'open': [('readonly', True)],
                'cancel': [('readonly', True)],
                'sent': [('readonly', True)],
                'rejected': [('readonly', True)],
                'done': [('readonly', True)]
            },
        ),
        'user_id': fields.many2one(
            'res.users','User', required=True,
            states={
                'sent': [('readonly', True)],
                'rejected': [('readonly', True)],
                'done': [('readonly', True)]
            },
        ),
        'date_prefered': fields.selection([
            ('now', 'Directly'),
            ('due', 'Due date'),
            ('fixed', 'Fixed date')
            ], "Preferred date", change_default=True, required=True,
            states={
                'sent': [('readonly', True)],
                'rejected': [('readonly', True)],
                'done': [('readonly', True)]
            },
            help=("Choose an option for the Payment Order:'Fixed' stands for a "
                  "date specified by you.'Directly' stands for the direct "
                  "execution.'Due date' stands for the scheduled date of "
                  "execution."
                 )
            ),
        'payment_order_type': fields.selection(
            [('payment', 'Payment'),('debit', 'Direct debit')],
            'Payment order type', required=True,
            ),
        'date_sent': fields.date('Send date', readonly=True),
    }

    _defaults = {
        'payment_order_type': 'payment',
        }

    def _write_payment_lines(self, cr, uid, ids, **kwargs):
        '''
        ORM method for setting attributes of corresponding payment.line objects.
        Note that while this is ORM compliant, it is also very ineffecient due
        to the absence of filters on writes and hence the requirement to
        filter on the client(=OpenERP server) side.
        '''
        if not hasattr(ids, '__iter__'):
            ids = [ids]
        payment_line_obj = self.pool.get('payment.line')
        line_ids = payment_line_obj.search(
            cr, uid, [
                ('order_id', 'in', ids)
            ])
        payment_line_obj.write(cr, uid, line_ids, kwargs)

    def action_rejected(self, cr, uid, ids, *args):
        '''
        Set both self and payment lines to state 'rejected'.
        '''
        wf_service = netsvc.LocalService('workflow')
        for id in ids:
            wf_service.trg_validate(uid, 'payment.order', id, 'rejected', cr)
        return True

    def set_done(self, cr, uid, ids, *args):
        '''
        Extend standard transition to update children as well.
        '''
        self._write_payment_lines(
            cr, uid, ids,
            date_done=fields.date.context_today(self, cr, uid))
        return super(payment_order, self).set_done(
            cr, uid, ids, *args
        )

    def debit_reconcile_transfer(self, cr, uid, payment_order_id,
                                 amount, currency, context=None):
        """
        During import of bank statements, create the reconcile on the transfer
        account containing all the open move lines on the transfer account.
        """
        move_line_obj = self.pool.get('account.move.line')
        order = self.browse(cr, uid, payment_order_id, context)
        line_ids = []
        reconcile_id = False
        if not order.line_ids[0].transit_move_line_id:
            wf_service = netsvc.LocalService('workflow')
            wf_service.trg_validate(
                uid, 'payment.order', payment_order_id, 'done', cr)
            return False
        for order_line in order.line_ids:
            for line in order_line.transit_move_line_id.move_id.line_id:
                if line.account_id.type == 'other' and not line.reconcile_id:
                    line_ids.append(line.id)
        if self.pool.get('res.currency').is_zero(
            cr, uid, currency,
            move_line_obj.get_balance(cr, uid, line_ids) - amount):
            reconcile_id = self.pool.get('account.move.reconcile').create(
                cr, uid,
                {'type': 'auto', 'line_id': [(6, 0, line_ids)]},
                context)
            # set direct debit order to finished state
            wf_service = netsvc.LocalService('workflow')
            wf_service.trg_validate(
                uid, 'payment.order', payment_order_id, 'done', cr)
        return reconcile_id

    def debit_unreconcile_transfer(self, cr, uid, payment_order_id, reconcile_id,
                                 amount, currency, context=None):
        """
        Due to a cancelled bank statements import, unreconcile the move on
        the transfer account. Delegate the conditions to the workflow.
        Raise on failure for rollback.

        Workflow appears to return False even on success so we just check
        the order's state that we know to be set to 'sent' in that case.
        """
        self.pool.get('account.move.reconcile').unlink(
            cr, uid, [reconcile_id], context=context)
        netsvc.LocalService('workflow').trg_validate(
            uid, 'payment.order', payment_order_id, 'undo_done', cr)
        state = self.pool.get('payment.order').read(
            cr, uid, payment_order_id, ['state'], context=context)['state']
        if state != 'sent':
            raise orm.except_orm(
                _("Cannot unreconcile"),
                _("Cannot unreconcile payment order: "+
                  "Workflow will not allow it."))
        return True

    def test_undo_done(self, cr, uid, ids, context=None):
        """
        Called from the workflow. Used to unset done state on
        payment orders that were reconciled with bank transfers
        which are being cancelled.

        Test if the payment order has not been reconciled. Depends
        on the restriction that transit move lines should use an
        account of type 'other', and on the restriction of payment
        and debit orders that they only take moves on accounts
        payable/receivable.
        """
        for order in self.browse(cr, uid, ids, context=context):
            for order_line in order.line_ids:
                if order_line.transit_move_line_id.move_id:
                    for line in order_line.transit_move_line_id.move_id.line_id:
                        if (line.account_id.type == 'other' and
                                line.reconcile_id):
                            return False
        return True

    def action_sent(self, cr, uid, ids, context=None):
        """
        Create the moves that pay off the move lines from
        the debit order. This happens when the debit order file is
        generated.
        """
        account_move_obj = self.pool.get('account.move')
        account_move_line_obj = self.pool.get('account.move.line')
        payment_line_obj = self.pool.get('payment.line')
        labels = {
            'payment': _('Payment order'),
            'debit': _('Direct debit order'),
            }
        for order in self.browse(cr, uid, ids, context=context):
            for line in order.line_ids:
                # basic checks
                if not line.move_line_id:
                    raise orm.except_orm(
                        _('Error'),
                        _('No move line provided for line %s') % line.name)
                if line.move_line_id.reconcile_id:
                    raise orm.except_orm(
                        _('Error'),
                        _('Move line %s has already been paid/reconciled') %
                        line.move_line_id.name
                        )

                move_id = account_move_obj.create(cr, uid, {
                        'journal_id': order.mode.transfer_journal_id.id,
                        'name': '%s %s' % (labels[order.payment_order_type],
                                           line.move_line_id.move_id.name),
                        'ref': '%s%s' % (order.payment_order_type[:3].upper(),
                                               line.move_line_id.move_id.name),
                        }, context=context)

                # TODO: take multicurrency into account

                # create the debit move line on the transfer account
                vals = {
                    'name': _('%s for %s') % (
                        labels[order.payment_order_type],
                        line.move_line_id.invoice and
                        line.move_line_id.invoice.number or
                        line.move_line_id.name),
                    'move_id': move_id,
                    'partner_id': False,
                    'account_id': order.mode.transfer_account_id.id,
                    'credit': (order.payment_order_type == 'payment'
                               and line.amount or 0.0),
                    'debit': (order.payment_order_type == 'debit'
                              and line.amount or 0.0),
                    'date': fields.date.context_today(
                        self, cr, uid, context=context),
                    }
                transfer_move_line_id = account_move_line_obj.create(
                    cr, uid, vals, context=context)

                # create the debit move line on the receivable account
                vals.update({
                        'partner_id': line.partner_id.id,
                        'account_id': line.move_line_id.account_id.id,
                        'credit': (order.payment_order_type == 'debit'
                                   and line.amount or 0.0),
                        'debit': (order.payment_order_type == 'payment'
                                   and line.amount or 0.0),
                        })
                reconcile_move_line_id = account_move_line_obj.create(
                    cr, uid, vals, context=context)

                # register the debit move line on the payment line
                # and call reconciliation on it
                payment_line_obj.write(
                    cr, uid, line.id,
                    {'transit_move_line_id': reconcile_move_line_id},
                    context=context)

                payment_line_obj.debit_reconcile(
                    cr, uid, line.id, context=context)
                account_move_obj.post(cr, uid, [move_id], context=context)

        # State field is written by act_sent_wait
        self.write(cr, uid, ids, {
                'date_sent': fields.date.context_today(
                    self, cr, uid, context=context),
                }, context=context)

        return True

<commit_msg>[FIX] handle situation where transfer account is not defined on payment order mode<commit_after># -*- coding: utf-8 -*-
##############################################################################
#
#    Copyright (C) 2009 EduSense BV (<http://www.edusense.nl>).
#              (C) 2011 - 2013 Therp BV (<http://therp.nl>).
#
#    All other contributions are (C) by their respective contributors
#
#    All Rights Reserved
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as
#    published by the Free Software Foundation, either version 3 of the
#    License, or (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################

from openerp.osv import orm, fields
from openerp.tools.translate import _
from openerp import netsvc

class payment_order(orm.Model):
    '''
    Enable extra states for payment exports
    '''
    _inherit = 'payment.order'

    _columns = {
        'date_scheduled': fields.date(
            'Scheduled date if fixed',
            states={
                'sent': [('readonly', True)],
                'rejected': [('readonly', True)],
                'done': [('readonly', True)]
            },
            help='Select a date if you have chosen Preferred Date to be fixed.'
        ),
        'reference': fields.char(
            'Reference', size=128, required=True,
            states={
                'sent': [('readonly', True)],
                'rejected': [('readonly', True)],
                'done': [('readonly', True)]
            },
        ),
        'mode': fields.many2one(
            'payment.mode', 'Payment mode', select=True, required=True,
            states={
                'sent': [('readonly', True)],
                'rejected': [('readonly', True)],
                'done': [('readonly', True)]
            },
            help='Select the Payment Mode to be applied.',
        ),
        'state': fields.selection([
            ('draft', 'Draft'),
            ('open','Confirmed'),
            ('cancel','Cancelled'),
            ('sent', 'Sent'),
            ('rejected', 'Rejected'),
            ('done','Done'),
            ], 'State', select=True
        ),
        'line_ids': fields.one2many(
            'payment.line', 'order_id', 'Payment lines',
            states={
                'open': [('readonly', True)],
                'cancel': [('readonly', True)],
                'sent': [('readonly', True)],
                'rejected': [('readonly', True)],
                'done': [('readonly', True)]
            },
        ),
        'user_id': fields.many2one(
            'res.users','User', required=True,
            states={
                'sent': [('readonly', True)],
                'rejected': [('readonly', True)],
                'done': [('readonly', True)]
            },
        ),
        'date_prefered': fields.selection([
            ('now', 'Directly'),
            ('due', 'Due date'),
            ('fixed', 'Fixed date')
            ], "Preferred date", change_default=True, required=True,
            states={
                'sent': [('readonly', True)],
                'rejected': [('readonly', True)],
                'done': [('readonly', True)]
            },
            help=("Choose an option for the Payment Order:'Fixed' stands for a "
                  "date specified by you.'Directly' stands for the direct "
                  "execution.'Due date' stands for the scheduled date of "
                  "execution."
                 )
            ),
        'payment_order_type': fields.selection(
            [('payment', 'Payment'),('debit', 'Direct debit')],
            'Payment order type', required=True,
            ),
        'date_sent': fields.date('Send date', readonly=True),
    }

    _defaults = {
        'payment_order_type': 'payment',
        }

    def _write_payment_lines(self, cr, uid, ids, **kwargs):
        '''
        ORM method for setting attributes of corresponding payment.line objects.
        Note that while this is ORM compliant, it is also very ineffecient due
        to the absence of filters on writes and hence the requirement to
        filter on the client(=OpenERP server) side.
        '''
        if not hasattr(ids, '__iter__'):
            ids = [ids]
        payment_line_obj = self.pool.get('payment.line')
        line_ids = payment_line_obj.search(
            cr, uid, [
                ('order_id', 'in', ids)
            ])
        payment_line_obj.write(cr, uid, line_ids, kwargs)

    def action_rejected(self, cr, uid, ids, *args):
        '''
        Set both self and payment lines to state 'rejected'.
        '''
        wf_service = netsvc.LocalService('workflow')
        for id in ids:
            wf_service.trg_validate(uid, 'payment.order', id, 'rejected', cr)
        return True

    def set_done(self, cr, uid, ids, *args):
        '''
        Extend standard transition to update children as well.
        '''
        self._write_payment_lines(
            cr, uid, ids,
            date_done=fields.date.context_today(self, cr, uid))
        return super(payment_order, self).set_done(
            cr, uid, ids, *args
        )

    def debit_reconcile_transfer(self, cr, uid, payment_order_id,
                                 amount, currency, context=None):
        """
        During import of bank statements, create the reconcile on the transfer
        account containing all the open move lines on the transfer account.
        """
        move_line_obj = self.pool.get('account.move.line')
        order = self.browse(cr, uid, payment_order_id, context)
        line_ids = []
        reconcile_id = False
        if not order.line_ids[0].transit_move_line_id:
            wf_service = netsvc.LocalService('workflow')
            wf_service.trg_validate(
                uid, 'payment.order', payment_order_id, 'done', cr)
            return False
        for order_line in order.line_ids:
            for line in order_line.transit_move_line_id.move_id.line_id:
                if line.account_id.type == 'other' and not line.reconcile_id:
                    line_ids.append(line.id)
        if self.pool.get('res.currency').is_zero(
            cr, uid, currency,
            move_line_obj.get_balance(cr, uid, line_ids) - amount):
            reconcile_id = self.pool.get('account.move.reconcile').create(
                cr, uid,
                {'type': 'auto', 'line_id': [(6, 0, line_ids)]},
                context)
            # set direct debit order to finished state
            wf_service = netsvc.LocalService('workflow')
            wf_service.trg_validate(
                uid, 'payment.order', payment_order_id, 'done', cr)
        return reconcile_id

    def debit_unreconcile_transfer(self, cr, uid, payment_order_id, reconcile_id,
                                 amount, currency, context=None):
        """
        Due to a cancelled bank statements import, unreconcile the move on
        the transfer account. Delegate the conditions to the workflow.
        Raise on failure for rollback.

        Workflow appears to return False even on success so we just check
        the order's state that we know to be set to 'sent' in that case.
        """
        self.pool.get('account.move.reconcile').unlink(
            cr, uid, [reconcile_id], context=context)
        netsvc.LocalService('workflow').trg_validate(
            uid, 'payment.order', payment_order_id, 'undo_done', cr)
        state = self.pool.get('payment.order').read(
            cr, uid, payment_order_id, ['state'], context=context)['state']
        if state != 'sent':
            raise orm.except_orm(
                _("Cannot unreconcile"),
                _("Cannot unreconcile payment order: "+
                  "Workflow will not allow it."))
        return True

    def test_undo_done(self, cr, uid, ids, context=None):
        """
        Called from the workflow. Used to unset done state on
        payment orders that were reconciled with bank transfers
        which are being cancelled.

        Test if the payment order has not been reconciled. Depends
        on the restriction that transit move lines should use an
        account of type 'other', and on the restriction of payment
        and debit orders that they only take moves on accounts
        payable/receivable.
        """
        for order in self.browse(cr, uid, ids, context=context):
            for order_line in order.line_ids:
                if order_line.transit_move_line_id.move_id:
                    for line in order_line.transit_move_line_id.move_id.line_id:
                        if (line.account_id.type == 'other' and
                                line.reconcile_id):
                            return False
        return True

    def action_sent(self, cr, uid, ids, context=None):
        """
        Create the moves that pay off the move lines from
        the debit order. This happens when the debit order file is
        generated.
        """
        account_move_obj = self.pool.get('account.move')
        account_move_line_obj = self.pool.get('account.move.line')
        payment_line_obj = self.pool.get('payment.line')
        labels = {
            'payment': _('Payment order'),
            'debit': _('Direct debit order'),
            }
        for order in self.browse(cr, uid, ids, context=context):
            if not order.mode.transfer_journal_id or not order.mode.transfer_account_id:
                continue
            for line in order.line_ids:
                # basic checks
                if not line.move_line_id:
                    raise orm.except_orm(
                        _('Error'),
                        _('No move line provided for line %s') % line.name)
                if line.move_line_id.reconcile_id:
                    raise orm.except_orm(
                        _('Error'),
                        _('Move line %s has already been paid/reconciled') %
                        line.move_line_id.name
                        )

                move_id = account_move_obj.create(cr, uid, {
                        'journal_id': order.mode.transfer_journal_id.id,
                        'name': '%s %s' % (labels[order.payment_order_type],
                                           line.move_line_id.move_id.name),
                        'ref': '%s%s' % (order.payment_order_type[:3].upper(),
                                               line.move_line_id.move_id.name),
                        }, context=context)

                # TODO: take multicurrency into account

                # create the debit move line on the transfer account
                vals = {
                    'name': _('%s for %s') % (
                        labels[order.payment_order_type],
                        line.move_line_id.invoice and
                        line.move_line_id.invoice.number or
                        line.move_line_id.name),
                    'move_id': move_id,
                    'partner_id': False,
                    'account_id': order.mode.transfer_account_id.id,
                    'credit': (order.payment_order_type == 'payment'
                               and line.amount or 0.0),
                    'debit': (order.payment_order_type == 'debit'
                              and line.amount or 0.0),
                    'date': fields.date.context_today(
                        self, cr, uid, context=context),
                    }
                transfer_move_line_id = account_move_line_obj.create(
                    cr, uid, vals, context=context)

                # create the debit move line on the receivable account
                vals.update({
                        'partner_id': line.partner_id.id,
                        'account_id': line.move_line_id.account_id.id,
                        'credit': (order.payment_order_type == 'debit'
                                   and line.amount or 0.0),
                        'debit': (order.payment_order_type == 'payment'
                                   and line.amount or 0.0),
                        })
                reconcile_move_line_id = account_move_line_obj.create(
                    cr, uid, vals, context=context)

                # register the debit move line on the payment line
                # and call reconciliation on it
                payment_line_obj.write(
                    cr, uid, line.id,
                    {'transit_move_line_id': reconcile_move_line_id},
                    context=context)

                payment_line_obj.debit_reconcile(
                    cr, uid, line.id, context=context)
                account_move_obj.post(cr, uid, [move_id], context=context)

        # State field is written by act_sent_wait
        self.write(cr, uid, ids, {
                'date_sent': fields.date.context_today(
                    self, cr, uid, context=context),
                }, context=context)

        return True

<|endoftext|>


<commit_before># coding: utf-8
from django.utils.six import u, b
from django import test
from model_mommy import mommy
import easy
from easy.helper import Nothing
from test_app.models import Question, Poll

class TestSimpleAdminField(test.TestCase):

    def test_simple(self):
        question = mommy.make(
            Question
        )

        custom_field = easy.SimpleAdminField('poll')
        ret = custom_field(question)

        self.assertEqual(ret, question.poll)
        self.assertEqual(custom_field.admin_order_field, 'poll')
        self.assertEqual(custom_field.short_description, 'poll')

    def test_simple_lambda(self):
        question = mommy.make(
            Question
        )

        custom_field = easy.SimpleAdminField(lambda obj: obj.poll, 'shorty')
        ret = custom_field(question)

        self.assertEqual(ret, question.poll)
        self.assertFalse(hasattr(custom_field, 'admin_order_field'))
        self.assertEqual(custom_field.short_description, 'shorty')

    def test_simple_default(self):
        question = mommy.make(
            Question
        )

        custom_field = easy.SimpleAdminField('not', default='default')
        ret = custom_field(question)

        self.assertEqual(ret, 'default')
        self.assertEqual(custom_field.short_description, 'not')

class TestBooleanAdminField(test.TestCase):
    def test_boolean(self):
        question = mommy.make(
            Question,
            question_text='Eba!'
        )

        custom_field = easy.BooleanAdminField(lambda x: x.question_text == "Eba!", 'Eba?')
        ret = custom_field(question)

        self.assertEqual(ret, True)
        self.assertTrue(custom_field.boolean)

class TestForeignKeyAdminField(test.TestCase):
    def test_foreignkey(self):
        question = mommy.make(
            Question,
            question_text='Eba!'
        )

        custom_field = easy.ForeignKeyAdminField('poll')
        ret = custom_field(question)

        expected = u'Poll object'

        self.assertEqual(expected, ret)
        self.assertTrue(custom_field.allow_tags)

class TestTemplateAdminField(test.TestCase):

    def test_template(self):
        question = mommy.make(
            Question,
            question_text='Eba!'
        )

        custom_field = easy.TemplateAdminField('test.html', {'a': '1'})
        ret = custom_field(question)

        expected = u'
Eba! - 1
'

        self.assertEqual(expected, ret)
        self.assertTrue(custom_field.allow_tags)

class TestLinkChangeListAdminField(test.TestCase):

    def test_link(self):
        poll = mommy.make(
            Poll,
        )

        custom_field = easy.LinkChangeListAdminField('test_app', 'question', 'question_set.count', {'pool': 'id'})
        ret = custom_field(poll)

        expected = u'0'

        self.assertEqual(expected, ret)
        self.assertTrue(custom_field.allow_tags)

class TestNothing(test.TestCase):

    def test_nothing(self):
        nothing = Nothing()

        self.assertEqual(nothing.__str__(), 'Error')
        self.assertEqual(nothing.__unicode__(), u'Error')

class TestSmartDecorator(test.TestCase):
    def test_link(self):

        @easy.smart(short_description='test', admin_order_field='test_field', allow_tags=True, boolean=True)
        def field(self, obj):
            return obj

        self.assertEqual(field.short_description, 'test')
        self.assertEqual(field.admin_order_field, 'test_field')
        self.assertEqual(field.allow_tags, True)
        self.assertEqual(field.boolean, True)
        self.assertEqual(field(object(), 1), 1)<commit_msg>create tests for short decorator and image admin field<commit_after># coding: utf-8
from django.utils.six import u, b
from django import test
from model_mommy import mommy
import easy
from easy.helper import Nothing
from test_app.models import Question, Poll

class TestSimpleAdminField(test.TestCase):

    def test_simple(self):
        question = mommy.make(
            Question
        )

        custom_field = easy.SimpleAdminField('poll')
        ret = custom_field(question)

        self.assertEqual(ret, question.poll)
        self.assertEqual(custom_field.admin_order_field, 'poll')
        self.assertEqual(custom_field.short_description, 'poll')

    def test_simple_lambda(self):
        question = mommy.make(
            Question
        )

        custom_field = easy.SimpleAdminField(lambda obj: obj.poll, 'shorty')
        ret = custom_field(question)

        self.assertEqual(ret, question.poll)
        self.assertFalse(hasattr(custom_field, 'admin_order_field'))
        self.assertEqual(custom_field.short_description, 'shorty')

    def test_simple_default(self):
        question = mommy.make(
            Question
        )

        custom_field = easy.SimpleAdminField('not', default='default')
        ret = custom_field(question)

        self.assertEqual(ret, 'default')
        self.assertEqual(custom_field.short_description, 'not')

class TestBooleanAdminField(test.TestCase):
    def test_boolean(self):
        question = mommy.make(
            Question,
            question_text='Eba!'
        )

        custom_field = easy.BooleanAdminField(lambda x: x.question_text == "Eba!", 'Eba?')
        ret = custom_field(question)

        self.assertEqual(ret, True)
        self.assertTrue(custom_field.boolean)

class TestForeignKeyAdminField(test.TestCase):
    def test_foreignkey(self):
        question = mommy.make(
            Question,
            question_text='Eba!'
        )

        custom_field = easy.ForeignKeyAdminField('poll')
        ret = custom_field(question)

        expected = u'Poll object'

        self.assertEqual(expected, ret)
        self.assertTrue(custom_field.allow_tags)

class TestTemplateAdminField(test.TestCase):

    def test_template(self):
        question = mommy.make(
            Question,
            question_text='Eba!'
        )

        custom_field = easy.TemplateAdminField('test.html', {'a': '1'})
        ret = custom_field(question)

        expected = u'
Eba! - 1
'

        self.assertEqual(expected, ret)
        self.assertTrue(custom_field.allow_tags)

class TestLinkChangeListAdminField(test.TestCase):

    def test_link(self):
        poll = mommy.make(
            Poll,
        )

        custom_field = easy.LinkChangeListAdminField('test_app', 'question', 'question_set.count', {'pool': 'id'})
        ret = custom_field(poll)

        expected = u'0'

        self.assertEqual(expected, ret)
        self.assertTrue(custom_field.allow_tags)

class TestImageField(test.TestCase):

    def test_image_field(self):
        question = mommy.make(
            Question,
            image='asd.jpg',
            question_text='bla'
        )

        custom_field = easy.ImageAdminField('image', {'title': 'question_text'})
        ret = custom_field(question)

        expected = u''

        self.assertEqual(expected, ret)
        self.assertTrue(custom_field.allow_tags)

class TestNothing(test.TestCase):

    def test_nothing(self):
        nothing = Nothing()

        self.assertEqual(nothing.__str__(), 'Error')
        self.assertEqual(nothing.__unicode__(), u'Error')

class TestSmartDecorator(test.TestCase):

    def test_decorator(self):

        @easy.smart(short_description='test', admin_order_field='test_field', allow_tags=True, boolean=True)
        def field(self, obj):
            return obj

        self.assertEqual(field.short_description, 'test')
        self.assertEqual(field.admin_order_field, 'test_field')
        self.assertEqual(field.allow_tags, True)
        self.assertEqual(field.boolean, True)
        self.assertEqual(field(object(), 1), 1)

class TestShortDecorator(test.TestCase):

    def test_decorator(self):

        @easy.short(desc='test', order='test_field', tags=True, bool=True)
        def field(self, obj):
            return obj

        self.assertEqual(field.short_description, 'test')
        self.assertEqual(field.admin_order_field, 'test_field')
        self.assertEqual(field.allow_tags, True)
        self.assertEqual(field.boolean, True)
        self.assertEqual(field(object(), 1), 1)<|endoftext|>


<commit_before>import os
import sys
import shutil
import tempfile
from os.path import dirname, isdir, isfile, join

if sys.platform != 'cli':
    print "ERROR: This setup script only works under IronPython"
    sys.exit(1)

src_dir = os.getcwd()

def msbuild():
    os.chdir(join(src_dir, 'numpy\NumpyDotNet'))
    os.system('msbuild')
    os.chdir(src_dir)

def write_config(path):
    fo = open(path, 'w')
    fo.write("""# this file is generated by ironsetup.py
__all__ = ["show"]
_config = {}
def show():
    print 'Numpy for IronPython'
""")
    fo.close()

def install():
    print "INSTALLING ..."
    sp_dir = join(sys.prefix, r'Lib\site-packages')
    numpy_dir = join(src_dir, 'numpy')
    bin_dir = join(numpy_dir, r'NumpyDotNet\bin\Debug')
    dll_dir = join(sys.prefix, 'DLLs')
    if not isdir(dll_dir):
        os.mkdir(dll_dir)
    for fn in ['ndarray.dll', 'NpyAccessLib.dll', 'NumpyDotNet.dll']:
        src = join(bin_dir, fn)
        dst = join(dll_dir, fn)
        if isfile(dst):
            tmp_dir = tempfile.mkdtemp()
            os.rename(dst, join(tmp_dir, fn))
        shutil.copyfile(src, dst)

    for root, dirs, files in os.walk(numpy_dir):
        for fn in files:
            if not fn.endswith('.py'):
                continue
            abs_path = join(root, fn)
            rel_path = abs_path[len(numpy_dir) + 1:]
            dst_dir = dirname(join(sp_dir, 'numpy', rel_path))
            if not isdir(dst_dir):
                 os.makedirs(dst_dir)
            shutil.copy(abs_path, dst_dir)
    write_config(join(sp_dir, r'numpy\__config__.py'))

if __name__ == '__main__':
    msbuild()
    install()
<commit_msg>added generation of umath code to ironsetup<commit_after>import os
import sys
import shutil
import tempfile
from os.path import dirname, isdir, isfile, join

if sys.platform != 'cli':
    print "ERROR: This setup script only works under IronPython"
    sys.exit(1)

src_dir = os.getcwd()

def gen_umath():
    os.chdir(join(src_dir, r'numpy\core'))
    os.system(r'ipy code_generators\generate_umath.py')
    os.chdir(src_dir)

def msbuild():
    os.chdir(join(src_dir, r'numpy\NumpyDotNet'))
    os.system('msbuild')
    os.chdir(src_dir)

def write_config(path):
    fo = open(path, 'w')
    fo.write("""# this file is generated by ironsetup.py
__all__ = ["show"]
_config = {}
def show():
    print 'Numpy for IronPython'
""")
    fo.close()

def install():
    print "INSTALLING ..."
    sp_dir = join(sys.prefix, r'Lib\site-packages')
    numpy_dir = join(src_dir, 'numpy')
    bin_dir = join(numpy_dir, r'NumpyDotNet\bin\Debug')
    dll_dir = join(sys.prefix, 'DLLs')
    if not isdir(dll_dir):
        os.mkdir(dll_dir)
    for fn in ['ndarray.dll', 'NpyAccessLib.dll', 'NumpyDotNet.dll']:
        src = join(bin_dir, fn)
        dst = join(dll_dir, fn)
        if isfile(dst):
            tmp_dir = tempfile.mkdtemp()
            os.rename(dst, join(tmp_dir, fn))
        shutil.copyfile(src, dst)

    for root, dirs, files in os.walk(numpy_dir):
        for fn in files:
            if not fn.endswith('.py'):
                continue
            abs_path = join(root, fn)
            rel_path = abs_path[len(numpy_dir) + 1:]
            dst_dir = dirname(join(sp_dir, 'numpy', rel_path))
            if not isdir(dst_dir):
                 os.makedirs(dst_dir)
            shutil.copy(abs_path, dst_dir)
    write_config(join(sp_dir, r'numpy\__config__.py'))

if __name__ == '__main__':
    gen_umath()
    msbuild()
    install()
<|endoftext|>


<commit_before>#
# Author    : Manuel Bernal Llinares
# Project   : trackhub-creator
# Timestamp : 03-07-2017 16:50
# ---
# © 2017 Manuel Bernal Llinares <mbdebian@gmail.com>
# All rights reserved.
#

"""
This module contains Ensembl models used as Entities and DAO/Services
"""

import config_manager

class Species:
    def __init__(self, ensembl_species_entry):
        self.__ensembl_species_entry = ensembl_species_entry
        self.__logger = config_manager.get_app_config_manager().get_logger_for(__name__)

    def _get_logger(self):
        return self.__logger

    def _get_value_for_key_or_default(self, key, default='-not_available-'):
        if key in self.get_ensembl_species_entry():
            return self.get_ensembl_species_entry()[key]
        return default

    def get_ensembl_species_entry(self):
        return self.__ensembl_species_entry

    def get_division(self):
        return self._get_value_for_key_or_default('division')

    def get_ncbi_taxonomy_id(self):
        return self._get_value_for_key_or_default('taxon_id')

    def get_name(self):
        return self._get_value_for_key_or_default('name')

    def get_ensembl_release(self):
        return self._get_value_for_key_or_default('release')

    def get_display_name(self):
        return self._get_value_for_key_or_default('display_name')

    def get_assembly_accession(self):
        return self._get_value_for_key_or_default('accession')

    def get_strain_collection(self):
        if self._get_value_for_key_or_default('strain_collection', 'null') == 'null':
            return None
        return self._get_value_for_key_or_default('strain_collection')

    def get_common_name(self):
        return self._get_value_for_key_or_default('common_name')

    def get_strain(self):
        return self._get_value_for_key_or_default('strain')

    def get_aliases(self):
        return self._get_value_for_key_or_default('aliases', [])

    def get_groups(self):
        return self._get_value_for_key_or_default('groups', [])

    def get_assembly(self):
        return self._get_value_for_key_or_default('assembly')

class SpeciesService:
    def __init__(self, species_data):
        self.__logger = config_manager.get_app_config_manager().get_logger_for(__name__)
        # De-reference the list of species objects, and just keep the list
        self.__species_data = species_data['species']
        self.__index_by_taxonomy_id = None

    @staticmethod
    def __index_data_for_property(data, property_getter):
        """
        Given an iterable data container, and a property getter to run on every object of that container, it returns a
        dictionary where the key is the property value for a particular data object part of the data collection
        :param data: iterable of data objects to index
        :param property_getter: property on which the index should be created
        :return: a dictionary of the given data objects where the key is the indexed property
        """
        return {property_getter(data_item): data_item for data_item in data}

    def _get_logger(self):
        return self.__logger

    def get_species_entry_for_taxonomy_id(self, taxonomy_id):
        # TODO
        pass
<commit_msg>protected getter for index based on taxonomy id<commit_after>#
# Author    : Manuel Bernal Llinares
# Project   : trackhub-creator
# Timestamp : 03-07-2017 16:50
# ---
# © 2017 Manuel Bernal Llinares <mbdebian@gmail.com>
# All rights reserved.
#

"""
This module contains Ensembl models used as Entities and DAO/Services
"""

import config_manager

class Species:
    def __init__(self, ensembl_species_entry):
        self.__ensembl_species_entry = ensembl_species_entry
        self.__logger = config_manager.get_app_config_manager().get_logger_for(__name__)

    def _get_logger(self):
        return self.__logger

    def _get_value_for_key_or_default(self, key, default='-not_available-'):
        if key in self.get_ensembl_species_entry():
            return self.get_ensembl_species_entry()[key]
        return default

    def get_ensembl_species_entry(self):
        return self.__ensembl_species_entry

    def get_division(self):
        return self._get_value_for_key_or_default('division')

    def get_ncbi_taxonomy_id(self):
        return self._get_value_for_key_or_default('taxon_id')

    def get_name(self):
        return self._get_value_for_key_or_default('name')

    def get_ensembl_release(self):
        return self._get_value_for_key_or_default('release')

    def get_display_name(self):
        return self._get_value_for_key_or_default('display_name')

    def get_assembly_accession(self):
        return self._get_value_for_key_or_default('accession')

    def get_strain_collection(self):
        if self._get_value_for_key_or_default('strain_collection', 'null') == 'null':
            return None
        return self._get_value_for_key_or_default('strain_collection')

    def get_common_name(self):
        return self._get_value_for_key_or_default('common_name')

    def get_strain(self):
        return self._get_value_for_key_or_default('strain')

    def get_aliases(self):
        return self._get_value_for_key_or_default('aliases', [])

    def get_groups(self):
        return self._get_value_for_key_or_default('groups', [])

    def get_assembly(self):
        return self._get_value_for_key_or_default('assembly')

class SpeciesService:
    def __init__(self, species_data):
        self.__logger = config_manager.get_app_config_manager().get_logger_for(__name__)
        # De-reference the list of species objects, and just keep the list
        self.__species_data = species_data['species']
        self.__index_by_taxonomy_id = None

    @staticmethod
    def __index_data_for_property(data, property_getter):
        """
        Given an iterable data container, and a property getter to run on every object of that container, it returns a
        dictionary where the key is the property value for a particular data object part of the data collection
        :param data: iterable of data objects to index
        :param property_getter: property on which the index should be created
        :return: a dictionary of the given data objects where the key is the indexed property
        """
        return {property_getter(data_item): data_item for data_item in data}

    def _get_logger(self):
        return self.__logger

    def _get_index_taxonomy_id(self):
        # TODO
        pass

    def get_species_entry_for_taxonomy_id(self, taxonomy_id):
        # TODO
        pass
<|endoftext|>


<commit_before>#!/usr/bin/env python
#########################################################################################
#
# Module containing several useful functions.
#
# ---------------------------------------------------------------------------------------
# Copyright (c) 2013 Polytechnique Montreal <www.neuro.polymtl.ca>
# Author: Julien Cohen-Adad
# Modified: 2014-07-01
#
# About the license: see the file LICENSE.TXT
#########################################################################################

import os
import sys
import commands

# TODO: under run(): add a flag "ignore error" for sct_ComposeMultiTransform
# TODO: check if user has bash or t-schell for fsloutput definition

fsloutput = 'export FSLOUTPUTTYPE=NIFTI; ' # for faster processing, all outputs are in NIFTI'

# define class color
class bcolors:
    blue = '\033[94m'
    green = '\033[92m'
    yellow = '\033[93m'
    red = '\033[91m'
    normal = '\033[0m'
    purple = '\033[95m'
    cyan = '\033[96m'
    bold = '\033[1m'
    underline = '\033[4m'

#==============e=========================================================================================================
# run
#=======================================================================================================================
# Run UNIX command
def run(cmd, verbose=1):
    if verbose:
        print(bcolors.blue+cmd+bcolors.normal)
    status, output = commands.getstatusoutput(cmd)
    if status != 0:
        printv('\nERROR! \n'+output+'\nExit program.\n', 1, 'error')
        sys.exit(2)
    else:
        return status, output

#=======================================================================================================================
# extract_fname
#=======================================================================================================================
# Extract path, file and extension
def extract_fname(fname):

    # extract path
    path_fname = os.path.dirname(fname)+'/'
    # check if only single file was entered (without path)
    if path_fname == '/':
        path_fname = ''
    # extract file and extension
    file_fname = fname
    file_fname = file_fname.replace(path_fname,'')
    file_fname, ext_fname = os.path.splitext(file_fname)
    # check if .nii.gz file
    if ext_fname == '.gz':
        file_fname = file_fname[0:len(file_fname)-4]
        ext_fname = ".nii.gz"

    return path_fname, file_fname, ext_fname

#=======================================================================================================================
# check_file_exist:  Check existence of a file or path
#=======================================================================================================================
def check_file_exist(fname, verbose=1):
    if os.path.isfile(fname) or os.path.isdir(fname):
        if verbose:
            printv('  OK: '+fname, verbose, 'normal')
        pass
    else:
        printv('\nERROR: ' + fname + ' does not exist. Exit program.\n', 1, 'error')

#=======================================================================================================================
# check_if_3d
#=======================================================================================================================
def check_if_3d(fname):
    nx, ny, nz, nt, px, py, pz, pt = get_dimension(fname)
    if not nt == 1:
        printv('\nERROR: '+fname+' is not a 3D volume. Exit program.\n', 1, 'error')

#=======================================================================================================================
# check_if_rpi:  check if data are in RPI orientation
#=======================================================================================================================
def check_if_rpi(fname):
    from sct_orientation import get_orientation
    if not get_orientation(fname) == 'RPI':
        printv('\nERROR: '+fname+' is not in RPI orientation. Use sct_orientation to reorient your data. Exit program.\n', 1, 'error')

#=======================================================================================================================
# find_file_within_folder
#=======================================================================================================================
def find_file_within_folder(fname, directory):
    """Find file (or part of file, e.g. 'my_file*.txt') within folder tree recursively - fname and directory must be
    strings"""
    import fnmatch

    all_path = []
    for root, dirs, files in os.walk(directory):
        for file in files:
            if fnmatch.fnmatch(file, fname):
                all_path.append(os.path.join(root, file))
    return all_path

#=======================================================================================================================
# get_dimension
#=======================================================================================================================
# Get dimensions of a nifti file using FSL
def get_dimension(fname):
    # apply fslsize on data
    cmd = 'fslsize '+fname
    status, output = commands.getstatusoutput(cmd)
    # split output according to \n field
    output_split = output.split()
    # extract dimensions as integer
    nx = int(output_split[1])
    ny = int(output_split[3])
    nz = int(output_split[5])
    nt = int(output_split[7])
    px = float(output_split[9])
    py = float(output_split[11])
    pz = float(output_split[13])
    pt = float(output_split[15])
    return nx, ny, nz, nt, px, py, pz, pt

#=======================================================================================================================
# generate_output_file
#=======================================================================================================================
def generate_output_file(fname_in, fname_out, verbose=1):
    # import stuff
    import shutil  # for moving files
    # get absolute fname
    fname_in = os.path.abspath(fname_in)
    fname_out = os.path.abspath(fname_out)
    # extract input file extension
    path_in, file_in, ext_in = extract_fname(fname_in)
    path_out, file_out, ext_out = extract_fname(fname_out)
    # if input image does not exist, give error
    if not os.path.isfile(fname_in):
        printv('  ERROR: File '+fname_in+' does not exist. Exit program.', 1, 'error')
        sys.exit(2)
    # if input and output fnames are the same, do nothing and exit function
    if fname_in == fname_out:
        printv('  WARNING: File '+path_out+file_out+ext_out+' same as output. Do nothing.', 1, 'warning')
        return path_out+file_out+ext_out
    # if fname_out already exists in nii or nii.gz
    if path_in != os.path.abspath(path_out):
        # first, check if path_in is different from path_out
        if os.path.isfile(path_out+file_out+'.nii'):
            printv('  WARNING: File '+path_out+file_out+'.nii'+' already exists. Deleting it...', 1, 'warning')
            os.system('rm '+path_out+file_out+'.nii')
        if os.path.isfile(path_out+file_out+'.nii.gz'):
            printv('  WARNING: File '+path_out+file_out+'.nii.gz'+' already exists. Deleting it...', 1, 'warning')
            os.system('rm '+path_out+file_out+'.nii.gz')
    # if path_in the same as path_out, only delete fname_out with specific ext_out extension
    else:
        if os.path.isfile(path_out+file_out+ext_out):
            printv('  WARNING: File '+path_out+file_out+ext_out+' already exists. Deleting it...', 1, 'warning')
            os.system('rm '+path_out+file_out+ext_out)
    # Move file to output folder (keep the same extension as input)
    shutil.move(fname_in, path_out+file_out+ext_in)
    # convert to nii (only if necessary)
    if ext_out == '.nii' and ext_in != '.nii':
        os.system('fslchfiletype NIFTI '+path_out+file_out)
    # convert to nii.gz (only if necessary)
    if ext_out == '.nii.gz' and ext_in != '.nii.gz':
        os.system('fslchfiletype NIFTI_GZ '+path_out+file_out)
    # display message
    if verbose:
        print '  File created: '+path_out+file_out+ext_out
    return path_out+file_out+ext_out

#=======================================================================================================================
# sign
#=======================================================================================================================
# Get the sign of a number. Returns 1 if x>=0 and -1 if x<0
def sign(x):
    if x >= 0:
        return 1
    else:
        return -1

#=======================================================================================================================
# check_if_installed
#=======================================================================================================================
# check if dependant software is installed
def check_if_installed(cmd, name_software):
    status, output = commands.getstatusoutput(cmd)
    if status != 0:
        print('\nERROR: '+name_software+' is not installed.\nExit program.\n')
        sys.exit(2)

#=======================================================================================================================
# printv: enables to print or not, depending on verbose status
#   type: handles color: normal (default), warning (orange), error (red)
#=======================================================================================================================
def printv(string, verbose=1, type='normal'):
    # select color based on type of message
    if type == 'normal':
        color = bcolors.normal
    if type == 'info':
        color = bcolors.green
    elif type == 'warning':
        color = bcolors.yellow
    elif type == 'error':
        color = bcolors.red
    elif type == 'code':
        color = bcolors.blue
    elif type == 'bold':
        color = bcolors.bold

    # print message
    if verbose:
        print(color+string+bcolors.normal)

    # if error, exit prohram
    if type == 'error':
        sys.exit(2)

#=======================================================================================================================
# slash_at_the_end: make sure there is (or not) a slash at the end of path name
#=======================================================================================================================
def slash_at_the_end(path, slash=0):
    if slash == 0:
        if path[-1:] == '/':
            path = path[:-1]
    if slash == 1:
        if not path[-1:] == '/':
            path = path+'/'
    return path

#=======================================================================================================================
# delete_nifti: delete nifti file(s)
#=======================================================================================================================
def delete_nifti(fname_in):
    # extract input file extension
    path_in, file_in, ext_in = extract_fname(fname_in)
    # delete nifti if exist
    if os.path.isfile(path_in+file_in+'.nii'):
        os.system('rm '+path_in+file_in+'.nii')
    # delete nifti if exist
    if os.path.isfile(path_in+file_in+'.nii.gz'):
        os.system('rm '+path_in+file_in+'.nii.gz')

#=======================================================================================================================
# create_folder:  create folder (check if exists before creating it)
#=======================================================================================================================
def create_folder(folder):
    if not os.path.exists(folder):
        os.makedirs(folder)

#=======================================================================================================================
# get_interpolation: get correct interpolation field depending on program used. Supported programs: ants, flirt, WarpImageMultiTransform
#=======================================================================================================================
def get_interpolation(program, interp):
    # TODO: check if field and program exists
    interp_program = ''
    # FLIRT
    if program == 'flirt':
        if interp == 'nn':
            interp_program = ' -interp nearestneighbour'
        elif interp == 'linear':
            interp_program = ' -interp trilinear'
        elif interp == 'spline':
            interp_program = ' -interp spline'
    # ANTs
    elif program == 'ants' or program == 'ants_affine' or program == 'sct_antsApplyTransforms' or program == 'sct_antsSliceRegularizedRegistration':
        if interp == 'nn':
            interp_program = ' -n NearestNeighbor'
        elif interp == 'linear':
            interp_program = ' -n Linear'
        elif interp == 'spline':
            interp_program = ' -n BSpline[3]'
    # check if not assigned
    if interp_program == '':
        printv('WARNING ('+os.path.basename(__file__)+'): interp_program not assigned. Using linear for ants_affine.', 1, 'warning')
        interp_program = ' -n Linear'
    # return
    return interp_program
<commit_msg>OPT: fixed issue #168<commit_after>#!/usr/bin/env python
#########################################################################################
#
# Module containing several useful functions.
#
# ---------------------------------------------------------------------------------------
# Copyright (c) 2013 Polytechnique Montreal <www.neuro.polymtl.ca>
# Author: Julien Cohen-Adad
# Modified: 2014-07-01
#
# About the license: see the file LICENSE.TXT
#########################################################################################

import os
import sys
import commands

# TODO: under run(): add a flag "ignore error" for sct_ComposeMultiTransform
# TODO: check if user has bash or t-schell for fsloutput definition

fsloutput = 'export FSLOUTPUTTYPE=NIFTI; ' # for faster processing, all outputs are in NIFTI'

# define class color
class bcolors:
    blue = '\033[94m'
    green = '\033[92m'
    yellow = '\033[93m'
    red = '\033[91m'
    normal = '\033[0m'
    purple = '\033[95m'
    cyan = '\033[96m'
    bold = '\033[1m'
    underline = '\033[4m'

#==============e=========================================================================================================
# run
#=======================================================================================================================
# Run UNIX command
def run(cmd, verbose=1):
    if verbose:
        print(bcolors.blue+cmd+bcolors.normal)
    status, output = commands.getstatusoutput(cmd)
    if status != 0:
        printv('\nERROR! \n'+output+'\nExit program.\n', 1, 'error')
        sys.exit(2)
    else:
        return status, output

#=======================================================================================================================
# extract_fname
#=======================================================================================================================
# Extract path, file and extension
def extract_fname(fname):

    # extract path
    path_fname = os.path.dirname(fname)+'/'
    # check if only single file was entered (without path)
    if path_fname == '/':
        path_fname = ''
    # extract file and extension
    file_fname = fname
    file_fname = file_fname.replace(path_fname,'')
    file_fname, ext_fname = os.path.splitext(file_fname)
    # check if .nii.gz file
    if ext_fname == '.gz':
        file_fname = file_fname[0:len(file_fname)-4]
        ext_fname = ".nii.gz"

    return path_fname, file_fname, ext_fname

#=======================================================================================================================
# check_file_exist:  Check existence of a file or path
#=======================================================================================================================
def check_file_exist(fname, verbose=1):
    if os.path.isfile(fname) or os.path.isdir(fname):
        if verbose:
            printv('  OK: '+fname, verbose, 'normal')
        pass
    else:
        printv('\nERROR: ' + fname + ' does not exist. Exit program.\n', 1, 'error')

#=======================================================================================================================
# check_if_3d
#=======================================================================================================================
def check_if_3d(fname):
    nx, ny, nz, nt, px, py, pz, pt = get_dimension(fname)
    if not nt == 1:
        printv('\nERROR: '+fname+' is not a 3D volume. Exit program.\n', 1, 'error')

#=======================================================================================================================
# check_if_rpi:  check if data are in RPI orientation
#=======================================================================================================================
def check_if_rpi(fname):
    from sct_orientation import get_orientation
    if not get_orientation(fname) == 'RPI':
        printv('\nERROR: '+fname+' is not in RPI orientation. Use sct_orientation to reorient your data. Exit program.\n', 1, 'error')

#=======================================================================================================================
# find_file_within_folder
#=======================================================================================================================
def find_file_within_folder(fname, directory):
    """Find file (or part of file, e.g. 'my_file*.txt') within folder tree recursively - fname and directory must be
    strings"""
    import fnmatch

    all_path = []
    for root, dirs, files in os.walk(directory):
        for file in files:
            if fnmatch.fnmatch(file, fname):
                all_path.append(os.path.join(root, file))
    return all_path

#=======================================================================================================================
# get_dimension
#=======================================================================================================================
# Get dimensions of a nifti file using FSL
def get_dimension(fname):
    # apply fslsize on data
    cmd = 'fslsize '+fname
    status, output = commands.getstatusoutput(cmd)
    # split output according to \n field
    output_split = output.split()
    # extract dimensions as integer
    nx = int(output_split[1])
    ny = int(output_split[3])
    nz = int(output_split[5])
    nt = int(output_split[7])
    px = float(output_split[9])
    py = float(output_split[11])
    pz = float(output_split[13])
    pt = float(output_split[15])
    return nx, ny, nz, nt, px, py, pz, pt

#=======================================================================================================================
# generate_output_file
#=======================================================================================================================
def generate_output_file(fname_in, fname_out, verbose=1):
    # import stuff
    import shutil  # for moving files
    # get absolute fname
    fname_in = os.path.abspath(fname_in)
    fname_out = os.path.abspath(fname_out)
    # extract input file extension
    path_in, file_in, ext_in = extract_fname(fname_in)
    path_out, file_out, ext_out = extract_fname(fname_out)
    # if input image does not exist, give error
    if not os.path.isfile(fname_in):
        printv('  ERROR: File '+fname_in+' does not exist. Exit program.', 1, 'error')
        sys.exit(2)
    # if input and output fnames are the same, do nothing and exit function
    if fname_in == fname_out:
        return path_out+file_out+ext_out
    # if fname_out already exists in nii or nii.gz
    if path_in != os.path.abspath(path_out):
        # first, check if path_in is different from path_out
        if os.path.isfile(path_out+file_out+'.nii'):
            printv('  WARNING: File '+path_out+file_out+'.nii'+' already exists. Deleting it...', 1, 'warning')
            os.system('rm '+path_out+file_out+'.nii')
        if os.path.isfile(path_out+file_out+'.nii.gz'):
            printv('  WARNING: File '+path_out+file_out+'.nii.gz'+' already exists. Deleting it...', 1, 'warning')
            os.system('rm '+path_out+file_out+'.nii.gz')
    # if path_in the same as path_out, only delete fname_out with specific ext_out extension
    else:
        if os.path.isfile(path_out+file_out+ext_out):
            printv('  WARNING: File '+path_out+file_out+ext_out+' already exists. Deleting it...', 1, 'warning')
            os.system('rm '+path_out+file_out+ext_out)
    # Move file to output folder (keep the same extension as input)
    shutil.move(fname_in, path_out+file_out+ext_in)
    # convert to nii (only if necessary)
    if ext_out == '.nii' and ext_in != '.nii':
        os.system('fslchfiletype NIFTI '+path_out+file_out)
    # convert to nii.gz (only if necessary)
    if ext_out == '.nii.gz' and ext_in != '.nii.gz':
        os.system('fslchfiletype NIFTI_GZ '+path_out+file_out)
    # display message
    if verbose:
        print '  File created: '+path_out+file_out+ext_out
    return path_out+file_out+ext_out

#=======================================================================================================================
# sign
#=======================================================================================================================
# Get the sign of a number. Returns 1 if x>=0 and -1 if x<0
def sign(x):
    if x >= 0:
        return 1
    else:
        return -1

#=======================================================================================================================
# check_if_installed
#=======================================================================================================================
# check if dependant software is installed
def check_if_installed(cmd, name_software):
    status, output = commands.getstatusoutput(cmd)
    if status != 0:
        print('\nERROR: '+name_software+' is not installed.\nExit program.\n')
        sys.exit(2)

#=======================================================================================================================
# printv: enables to print or not, depending on verbose status
#   type: handles color: normal (default), warning (orange), error (red)
#=======================================================================================================================
def printv(string, verbose=1, type='normal'):
    # select color based on type of message
    if type == 'normal':
        color = bcolors.normal
    if type == 'info':
        color = bcolors.green
    elif type == 'warning':
        color = bcolors.yellow
    elif type == 'error':
        color = bcolors.red
    elif type == 'code':
        color = bcolors.blue
    elif type == 'bold':
        color = bcolors.bold

    # print message
    if verbose:
        print(color+string+bcolors.normal)

    # if error, exit prohram
    if type == 'error':
        sys.exit(2)

#=======================================================================================================================
# slash_at_the_end: make sure there is (or not) a slash at the end of path name
#=======================================================================================================================
def slash_at_the_end(path, slash=0):
    if slash == 0:
        if path[-1:] == '/':
            path = path[:-1]
    if slash == 1:
        if not path[-1:] == '/':
            path = path+'/'
    return path

#=======================================================================================================================
# delete_nifti: delete nifti file(s)
#=======================================================================================================================
def delete_nifti(fname_in):
    # extract input file extension
    path_in, file_in, ext_in = extract_fname(fname_in)
    # delete nifti if exist
    if os.path.isfile(path_in+file_in+'.nii'):
        os.system('rm '+path_in+file_in+'.nii')
    # delete nifti if exist
    if os.path.isfile(path_in+file_in+'.nii.gz'):
        os.system('rm '+path_in+file_in+'.nii.gz')

#=======================================================================================================================
# create_folder:  create folder (check if exists before creating it)
#=======================================================================================================================
def create_folder(folder):
    if not os.path.exists(folder):
        os.makedirs(folder)

#=======================================================================================================================
# get_interpolation: get correct interpolation field depending on program used. Supported programs: ants, flirt, WarpImageMultiTransform
#=======================================================================================================================
def get_interpolation(program, interp):
    # TODO: check if field and program exists
    interp_program = ''
    # FLIRT
    if program == 'flirt':
        if interp == 'nn':
            interp_program = ' -interp nearestneighbour'
        elif interp == 'linear':
            interp_program = ' -interp trilinear'
        elif interp == 'spline':
            interp_program = ' -interp spline'
    # ANTs
    elif program == 'ants' or program == 'ants_affine' or program == 'sct_antsApplyTransforms' or program == 'sct_antsSliceRegularizedRegistration':
        if interp == 'nn':
            interp_program = ' -n NearestNeighbor'
        elif interp == 'linear':
            interp_program = ' -n Linear'
        elif interp == 'spline':
            interp_program = ' -n BSpline[3]'
    # check if not assigned
    if interp_program == '':
        printv('WARNING ('+os.path.basename(__file__)+'): interp_program not assigned. Using linear for ants_affine.', 1, 'warning')
        interp_program = ' -n Linear'
    # return
    return interp_program
<|endoftext|>