<commit_before>#! /usr/bin/python3.5
# -* coding:utf-8 -*-

import neuralNet
import numpy as np
import copy
import matplotlib.pyplot as plt
import tqdm
import line_profiler

class Particule():
    """
    Il s'agit de la classe particule. Elle dispose de différents attributs:
        - index -> pour identifier de manière unique la particule
        - theta{1,2}_size -> qui donne la taille des matrices theta1 et theta2
        - theta{1,2} -> des arrays numpy
        - v -> notre vecteur vitesse de taille : |v| = |theta1| + |theta2|
        - best -> le meilleur vecteur rencontrer
        - fitnessValue -> la valeur acctuelle pour tetha1,theta2
        - bestValue -> la valeur du vecteur best
    """

    def __init__(self, index, size_theta1, size_theta2, images, labels):
        """Fonction d'initialisation

        La méthode __init__ permet d'initialiser les différents attributs de la classe
        particule.

        Arguments:
            index {int} -- l'index de la particule
            size_theta1 {[int]} -- taille [x,y] de la matrice theta1
            size_theta2 {[int]} -- taille [x,y] de la matrice theta2
            images {np.matrix} -- une matrice contenant toutes les images
            labels {np.matrix} -- une matrice contenant les labels.

        """
        self.index = index
        self.theta1_size = size_theta1
        self.theta2_size = size_theta2
        self.theta1 = (1 - (- 1)) * np.random.random_sample(size_theta1[0] * size_theta1[1]) + -1
        self.theta2 = (1 - (- 1)) * np.random.random_sample(size_theta2[0] * size_theta2[1]) + -1
        self.v = np.random.rand(size_theta1[0] * size_theta1[1] + size_theta2[0] * size_theta2[1])
        self.best = np.append(self.theta1, self.theta2)
        self.fitnessValue = self.fitness(images, labels)
        self.bestValue = self.fitnessBest(images, labels)

    def update(self, omega, c1, r1, c2, r2, bestGlobal, cut_off):
        """Mise à jour de la vitesse et de la position.

        La méthode update va calculer la nouvelle vitesse:
            1. v = omega * v + c1 * r1 * (bestLocal - vecteurLocal) + c2 * r2 * (bestGlobal - vecteurLocal)
        Puis calculer la nouvelle position:
            2. s = s + v

        Arguments:
            omega {float} -- un coefficient multiplicatif
            c1 {int} -- une constante
            r1 {float} -- un nombre aléatoire [0,1]
            c2 {int} -- une constante
            r2 {float} -- un nombre aléatoire [0,1]
            bestGlobal {np.array} -- la position de l'optimum global
            cut_off {bool} -- dit si on applique le cut off ou non
        """
        theta = np.append(self.theta1, self.theta2)
        best = np.append(bestGlobal.theta1, bestGlobal.theta2)
        self.v = omega * self.v + c1 * r1 * (self.best - theta) + c2 * r2 * (best - theta)
        if cut_off:
            self.v = np.where(np.abs(self.v) > 0.5, 0, self.v)
        theta += self.v
        self.theta1 = theta[0: self.theta1_size[0] * self.theta1_size[1]]
        self.theta2 = theta[self.theta1_size[0] * self.theta1_size[1]:]

    # @profile
    def fitness(self, images, labels):
        """Évaluation du réseau avec toutes les images.

        La fitness est juste l'évaluation du réseau de neurone sur toutes les images de l'ensemble d'entrainements.
        Il y a une composition de fonction:
            1. np.where(vecteur >= 0.5, 1, 0) -> met les éléments du vecteur à 1 si  la valeur est >= 0.5 , à 0 sinon.
            2. theta{1,2}.reshape(theta{1,2}_size) -> permet de passer d'un tableau t x 1 à un tableau  m x n. Où m et n sont
                les valeurs définies par tetha{1,2}_size.
            3. np.array(labels) - np.array(liste) -> va soustraire les éléments 1 à 1.
            4. sum([x*x for x in res]) / len(images) -> calcule le carré de chaque éléments puis divise par la longueur.
            5. on assigne la valeur de 4 à l'atribut fitnessValue

        Arguments:
            images {np.matrix} -- la matrice d'image
            labels {np.matrix} -- la matrice des labels

        Returns:
            float -- le nombre d'erreur au carré moyennée.
        """

        liste = neuralNet.fitness(self.theta1.reshape(self.theta1_size), self.theta2.reshape(self.theta2_size), 1, images)
        liste = np.where(np.array(liste) >= 0.5, 1, 0)
        res = np.array(labels) - np.array(liste)
        self.fitnessValue = sum([x * x for x in res]) / len(images)
        return self.fitnessValue

    def fitnessBest(self, images, labels):
        """Évaluation du réseau avec toutes les images.

        Le code est semblable à la méthode fitness, cependant il faut extraire la valeur de best, qui est un
        tableau en deux tableaux theta{1,2}. Puis même code que fitness, sauf qu'on retourne la valeur calculée.

        Arguments:
            images {np.matrix} -- la matrice d'image
            labels {np.matrix} -- la matrice des labels

        Returns:
        float -- le nombre d'erreur au carré moyennée.
        """

        theta1 = self.best[0: self.theta1_size[0] * self.theta1_size[1]]
        theta2 = self.best[self.theta1_size[0] * self.theta1_size[1]:]
        liste = neuralNet.fitness(theta1.reshape(self.theta1_size), theta2.reshape(self.theta2_size), 1, images)
        liste = np.where(np.array(liste) >= 0.5, 1, 0)
        res = np.array(labels) - np.array(liste)
        return sum([x * x for x in res]) / len(images)

    def updateBest(self, images, labels):
        """Mise à jour du meilleur résultat rencontré

        On vérifie si la valeur du meilleure est plus grande que la valeur acctuelle. Si oui, on met à jour le meilleur.
        Pour la mise à jour, on copie le vecteur actuel dans le vecteur best, et on met à jour la valeur de l'atribut
        bestValue.

        Arguments:
            images {np.matrix} -- la matrice d'image
            labels {np.matrix} -- la matrice des labels
        """
        if self.fitnessValue < self.bestValue:
            self.best = np.append(self.theta1, self.theta2)
            self.bestValue = copy.deepcopy(self.fitnessValue)

class Espace():
    """
    Espace est une classe qui contient un ensemble de particule;
        - particule -> un tableau de particules
        - bestGlobal -> le meilleur individu de l'espace
    """

    def __init__(self, size_theta1, size_theta2, number, images, labels):
        """Fonction d'initialisation

        Pour la méthode __init__, on va instancier n particules. cf: méthode __init__ particules.

        Arguments:
            size_theta1 {[int]} -- taille [x,y] de la matrice theta1
            size_theta2 {[int]} -- taille [x,y] de la matrice theta2
            number {int} -- nombre de particule de l'espace
            images {np.matrix} -- la matrice d'image
            labels {np.matrix} -- la matrice des labels
        """
        self.particule = []
        for index in range(number):
            self.particule.append(Particule(index, size_theta1, size_theta2, images, labels))

    def initBest(self):
        """Initialisation du bestGlobal

        On va trouver le min des particules, puis prendre la plus petite particule et la
        copier dans l'attribut bestGlobal
        """
        res = (list(map(lambda x: x.fitnessValue, self.particule)))
        index = res.index(min(res))
        self.bestGlobal = copy.deepcopy(self.particule[index])

    def findBest(self):
        """Mise à jour du bestGlobal

        Même principe que initBest, sauf qu'on vérifie si la valeur du bestGlobal
        est plus grande que celle du meilleur individu courrant de l'espace
        """
        res = [x.bestValue for x in self.particule]
        index = res.index(min(res))
        if self.particule[index].bestValue < self.bestGlobal.bestValue:
            self.bestGlobal = copy.deepcopy(self.particule[index])

    def getFitness(self):
        """
        Permet de récupérer la fitness de toutes les particules de l'espaces

        Returns:
            [float] -- la fitness courrante de chaque particule
        """
        res = [x.fitnessValue for x in self.particule]
        return res

def update(x, omega, c1, c2, bestGlobal, cut_off):
    """Mise à jour d'une particule

    On assume que x est un objet particule. C'est une interface pour appliquer la méthode update
    aux particules

    Arguments:
        x {particule} -- la particule dont on veut mettre à jour les valeurs
        omega {float} -- la valeur de la constante omega
        c1 {int} -- valeur de la constante c1
        c2 {int} -- valeur de la constante c2
        bestGlobal {np.array} -- la postion du meilleur de l'espace
        cut_off {bool} -- applique ou non le cut off
    """

    x.update(omega, c1, np.random.rand(), c2, np.random.rand(), bestGlobal, cut_off)

def main(particuleNumbers, xPath, yPath, t1, t2, t_max, cut_off):
    """Algorithme PSO

    Applique l'algorithme PSO sur les paramètres.

    Arguments:
        particuleNumbers {int} -- nombre de particules
        xPath {string} -- un chemin jusqu'au fichier
        yPath {string} -- un chemin jusqu'au fichier
        t1 {[int]} -- taille de la matrice theta1
        t2 {[int]} -- taille de la matrice theta2
        t_max {int} -- nombre d'itération
        cut_off {bool} -- dis s'il y a un cut off ou non

    Returns:
        [],np.array,np.array -- donne une liste avec la valeur de la fitness du global best,
        ainsi que les meilleures theta{1,2}
    """

    # on initialise les images et les labels depuis les fichiers.
    images, labels = neuralNet.read_image(xPath, yPath, 200)
    # on crée l'espace des particules
    e = Espace(t1, t2, particuleNumbers, images, labels)
    # on trouve le best global
    e.initBest()
    res = []
    # init constante
    omega = 0.75
    c1 = 2
    c2 = 2

    for x in tqdm.tqdm(range(t_max)):
        # calculate its fitness
        [x.fitness(images, labels) for x in e.particule]
        # update the best
        [x.updateBest(images, labels) for x in e.particule]
        # find the absolute best
        e.findBest()
        res.append(e.bestGlobal.fitnessValue)
        # mise à jour de la vitesse
        [update(x, omega, c1, c2, e.bestGlobal, cut_off) for x in e.particule]

    # on retourne les meilleures matrices pour faire des tests
    theta1 = e.bestGlobal.best[0: e.bestGlobal.theta1_size[0] * e.bestGlobal.theta1_size[1]].reshape(e.bestGlobal.theta1_size)
    theta2 = e.bestGlobal.best[e.bestGlobal.theta1_size[0] * e.bestGlobal.theta1_size[1]:].reshape(e.bestGlobal.theta2_size)
    return res, theta1, theta2

def print_data(array):
    """Afficher des données

    Afficher le min, le max, la moyenne et la déviation standard.

    Arguments:
        array {np.arry} -- le vecteur numpy dont on veut les infos
    """
    print("Min : " + str(array.min()))
    print("Max : " + str(array.max()))
    print("Mean: " + str(array.mean()))
    print("Std : " + str(array.std()))

def plot(boolean):
    """Plot
    Simple fonction qui lance le PSO, et qui plot les résultats
    """
    n = 100
    t_max = 70
    res, theta1, theta2 = main(particuleNumbers=n, xPath='X.data', yPath='Y.data', t1=[25, 401], t2=[1, 26], t_max=t_max, cut_off=boolean)
    plt.plot(res, label="Fitness")
    plt.ylabel("$J(\Theta^{(1)},\Theta^{(2)})$")
    plt.xlabel("Itérations")
    plt.title("$t_{max} = " + str(t_max) + "$, et " + str(n) + " particules")
    plt.show()

    print("Theta1 : ")
    print_data(theta1)
    print("\nTheta2:")
    print_data(theta2)

    images, labels = neuralNet.read_image('X.data', 'Y.data', 200)
    new_res = np.where(neuralNet.fitness(theta1, theta2, 1, images) >= 0.5, 1, 0) - np.array(labels)
    new_res = 100 - (np.sum(np.abs(new_res)) / 200) * 100
    print("Accuracy : " + str(new_res) + "%")

def ten_times(boolean):
    """Lance 10 fois l'algorithme PSO

    On va lancer 10 fois l'algorithme, en récupérant la fitness du best à chaque fois.
    On print ces valeurs
    """
    n = 30
    liste = []
    res2 = []
    for x in range(10):
        print("Itération : " + str(x))
        res, _, _ = main(particuleNumbers=n, xPath='X.data', yPath='Y.data', t1=[25, 401], t2=[1, 26], t_max=40, cut_off=boolean)
        liste.append(res)

    for ele in liste:
        res2.append(min(ele))
    print(res2)

if __name__ == '__main__':
    plot(True)
    # ten_times(False)
<commit_msg>modification du cut off<commit_after>#! /usr/bin/python3.5
# -* coding:utf-8 -*-

import neuralNet
import numpy as np
import copy
import matplotlib.pyplot as plt
import tqdm
import line_profiler

class Particule():
    """
    Il s'agit de la classe particule. Elle dispose de différents attributs:
        - index -> pour identifier de manière unique la particule
        - theta{1,2}_size -> qui donne la taille des matrices theta1 et theta2
        - theta{1,2} -> des arrays numpy
        - v -> notre vecteur vitesse de taille : |v| = |theta1| + |theta2|
        - best -> le meilleur vecteur rencontrer
        - fitnessValue -> la valeur acctuelle pour tetha1,theta2
        - bestValue -> la valeur du vecteur best
    """

    def __init__(self, index, size_theta1, size_theta2, images, labels):
        """Fonction d'initialisation

        La méthode __init__ permet d'initialiser les différents attributs de la classe
        particule.

        Arguments:
            index {int} -- l'index de la particule
            size_theta1 {[int]} -- taille [x,y] de la matrice theta1
            size_theta2 {[int]} -- taille [x,y] de la matrice theta2
            images {np.matrix} -- une matrice contenant toutes les images
            labels {np.matrix} -- une matrice contenant les labels.

        """
        self.index = index
        self.theta1_size = size_theta1
        self.theta2_size = size_theta2
        self.theta1 = (1 - (- 1)) * np.random.random_sample(size_theta1[0] * size_theta1[1]) + -1
        self.theta2 = (1 - (- 1)) * np.random.random_sample(size_theta2[0] * size_theta2[1]) + -1
        self.v = np.random.rand(size_theta1[0] * size_theta1[1] + size_theta2[0] * size_theta2[1])
        self.best = np.append(self.theta1, self.theta2)
        self.fitnessValue = self.fitness(images, labels)
        self.bestValue = self.fitnessBest(images, labels)

    def update(self, omega, c1, r1, c2, r2, bestGlobal, cut_off, vmax):
        """Mise à jour de la vitesse et de la position.

        La méthode update va calculer la nouvelle vitesse:
            1. v = omega * v + c1 * r1 * (bestLocal - vecteurLocal) + c2 * r2 * (bestGlobal - vecteurLocal)
        Puis calculer la nouvelle position:
            2. s = s + v

        Arguments:
            omega {float} -- un coefficient multiplicatif
            c1 {int} -- une constante
            r1 {float} -- un nombre aléatoire [0,1]
            c2 {int} -- une constante
            r2 {float} -- un nombre aléatoire [0,1]
            bestGlobal {np.array} -- la position de l'optimum global
            cut_off {bool} -- dit si on applique le cut off ou non
        """
        theta = np.append(self.theta1, self.theta2)
        best = np.append(bestGlobal.theta1, bestGlobal.theta2)
        self.v = omega * self.v + c1 * r1 * (self.best - theta) + c2 * r2 * (best - theta)
        if cut_off:
            self.v = np.where(self.v > vmax, vmax, self.v)
            self.v = np.where(self.v < -vmax, -vmax, self.v)
        theta += self.v
        self.theta1 = theta[0: self.theta1_size[0] * self.theta1_size[1]]
        self.theta2 = theta[self.theta1_size[0] * self.theta1_size[1]:]

    # @profile
    def fitness(self, images, labels):
        """Évaluation du réseau avec toutes les images.

        La fitness est juste l'évaluation du réseau de neurone sur toutes les images de l'ensemble d'entrainements.
        Il y a une composition de fonction:
            1. np.where(vecteur >= 0.5, 1, 0) -> met les éléments du vecteur à 1 si  la valeur est >= 0.5 , à 0 sinon.
            2. theta{1,2}.reshape(theta{1,2}_size) -> permet de passer d'un tableau t x 1 à un tableau  m x n. Où m et n sont
                les valeurs définies par tetha{1,2}_size.
            3. np.array(labels) - np.array(liste) -> va soustraire les éléments 1 à 1.
            4. sum([x*x for x in res]) / len(images) -> calcule le carré de chaque éléments puis divise par la longueur.
            5. on assigne la valeur de 4 à l'atribut fitnessValue

        Arguments:
            images {np.matrix} -- la matrice d'image
            labels {np.matrix} -- la matrice des labels

        Returns:
            float -- le nombre d'erreur au carré moyennée.
        """

        liste = neuralNet.fitness(self.theta1.reshape(self.theta1_size), self.theta2.reshape(self.theta2_size), 1, images)
        liste = np.where(np.array(liste) >= 0.5, 1, 0)
        res = np.array(labels) - np.array(liste)
        self.fitnessValue = sum([x * x for x in res]) / len(images)
        return self.fitnessValue

    def fitnessBest(self, images, labels):
        """Évaluation du réseau avec toutes les images.

        Le code est semblable à la méthode fitness, cependant il faut extraire la valeur de best, qui est un
        tableau en deux tableaux theta{1,2}. Puis même code que fitness, sauf qu'on retourne la valeur calculée.

        Arguments:
            images {np.matrix} -- la matrice d'image
            labels {np.matrix} -- la matrice des labels

        Returns:
        float -- le nombre d'erreur au carré moyennée.
        """

        theta1 = self.best[0: self.theta1_size[0] * self.theta1_size[1]]
        theta2 = self.best[self.theta1_size[0] * self.theta1_size[1]:]
        liste = neuralNet.fitness(theta1.reshape(self.theta1_size), theta2.reshape(self.theta2_size), 1, images)
        liste = np.where(np.array(liste) >= 0.5, 1, 0)
        res = np.array(labels) - np.array(liste)
        return sum([x * x for x in res]) / len(images)

    def updateBest(self, images, labels):
        """Mise à jour du meilleur résultat rencontré

        On vérifie si la valeur du meilleure est plus grande que la valeur acctuelle. Si oui, on met à jour le meilleur.
        Pour la mise à jour, on copie le vecteur actuel dans le vecteur best, et on met à jour la valeur de l'atribut
        bestValue.

        Arguments:
            images {np.matrix} -- la matrice d'image
            labels {np.matrix} -- la matrice des labels
        """
        if self.fitnessValue < self.bestValue:
            self.best = np.append(self.theta1, self.theta2)
            self.bestValue = copy.deepcopy(self.fitnessValue)

class Espace():
    """
    Espace est une classe qui contient un ensemble de particule;
        - particule -> un tableau de particules
        - bestGlobal -> le meilleur individu de l'espace
    """

    def __init__(self, size_theta1, size_theta2, number, images, labels):
        """Fonction d'initialisation

        Pour la méthode __init__, on va instancier n particules. cf: méthode __init__ particules.

        Arguments:
            size_theta1 {[int]} -- taille [x,y] de la matrice theta1
            size_theta2 {[int]} -- taille [x,y] de la matrice theta2
            number {int} -- nombre de particule de l'espace
            images {np.matrix} -- la matrice d'image
            labels {np.matrix} -- la matrice des labels
        """
        self.particule = []
        for index in range(number):
            self.particule.append(Particule(index, size_theta1, size_theta2, images, labels))

    def initBest(self):
        """Initialisation du bestGlobal

        On va trouver le min des particules, puis prendre la plus petite particule et la
        copier dans l'attribut bestGlobal
        """
        res = (list(map(lambda x: x.fitnessValue, self.particule)))
        index = res.index(min(res))
        self.bestGlobal = copy.deepcopy(self.particule[index])

    def findBest(self):
        """Mise à jour du bestGlobal

        Même principe que initBest, sauf qu'on vérifie si la valeur du bestGlobal
        est plus grande que celle du meilleur individu courrant de l'espace
        """
        res = [x.bestValue for x in self.particule]
        index = res.index(min(res))
        if self.particule[index].bestValue < self.bestGlobal.bestValue:
            self.bestGlobal = copy.deepcopy(self.particule[index])

    def getFitness(self):
        """
        Permet de récupérer la fitness de toutes les particules de l'espaces

        Returns:
            [float] -- la fitness courrante de chaque particule
        """
        res = [x.fitnessValue for x in self.particule]
        return res

def update(x, omega, c1, c2, bestGlobal, cut_off, vmax):
    """Mise à jour d'une particule

    On assume que x est un objet particule. C'est une interface pour appliquer la méthode update
    aux particules

    Arguments:
        x {particule} -- la particule dont on veut mettre à jour les valeurs
        omega {float} -- la valeur de la constante omega
        c1 {int} -- valeur de la constante c1
        c2 {int} -- valeur de la constante c2
        bestGlobal {np.array} -- la postion du meilleur de l'espace
        cut_off {bool} -- applique ou non le cut off
    """

    x.update(omega, c1, np.random.rand(), c2, np.random.rand(), bestGlobal, cut_off, vmax)

def main(particuleNumbers, xPath, yPath, t1, t2, t_max, cut_off, vmax):
    """Algorithme PSO

    Applique l'algorithme PSO sur les paramètres.

    Arguments:
        particuleNumbers {int} -- nombre de particules
        xPath {string} -- un chemin jusqu'au fichier
        yPath {string} -- un chemin jusqu'au fichier
        t1 {[int]} -- taille de la matrice theta1
        t2 {[int]} -- taille de la matrice theta2
        t_max {int} -- nombre d'itération
        cut_off {bool} -- dis s'il y a un cut off ou non

    Returns:
        [],np.array,np.array -- donne une liste avec la valeur de la fitness du global best,
        ainsi que les meilleures theta{1,2}
    """

    # on initialise les images et les labels depuis les fichiers.
    images, labels = neuralNet.read_image(xPath, yPath, 200)
    # on crée l'espace des particules
    e = Espace(t1, t2, particuleNumbers, images, labels)
    # on trouve le best global
    e.initBest()
    res = []
    # init constante
    omega = 0.75
    c1 = 2
    c2 = 2

    for x in tqdm.tqdm(range(t_max)):
        # calculate its fitness
        [x.fitness(images, labels) for x in e.particule]
        # update the best
        [x.updateBest(images, labels) for x in e.particule]
        # find the absolute best
        e.findBest()
        res.append(e.bestGlobal.fitnessValue)
        # mise à jour de la vitesse
        [update(x, omega, c1, c2, e.bestGlobal, cut_off, vmax) for x in e.particule]

    # on retourne les meilleures matrices pour faire des tests
    theta1 = e.bestGlobal.best[0: e.bestGlobal.theta1_size[0] * e.bestGlobal.theta1_size[1]].reshape(e.bestGlobal.theta1_size)
    theta2 = e.bestGlobal.best[e.bestGlobal.theta1_size[0] * e.bestGlobal.theta1_size[1]:].reshape(e.bestGlobal.theta2_size)
    return res, theta1, theta2

def print_data(array):
    """Afficher des données

    Afficher le min, le max, la moyenne et la déviation standard.

    Arguments:
        array {np.arry} -- le vecteur numpy dont on veut les infos
    """
    print("Min : " + str(array.min()))
    print("Max : " + str(array.max()))
    print("Mean: " + str(array.mean()))
    print("Std : " + str(array.std()))

def plot(boolean):
    """Plot
    Simple fonction qui lance le PSO, et qui plot les résultats
    """
    n = 100
    t_max = 70
    vmax = 0.3
    res, theta1, theta2 = main(particuleNumbers=n, xPath='X.data', yPath='Y.data'\
        , t1=[25, 401], t2=[1, 26], t_max=t_max, cut_off=boolean, vmax=vmax)
    plt.plot(res, label="Fitness")
    plt.ylabel("$J(\Theta^{(1)},\Theta^{(2)})$")
    plt.xlabel("Itérations")
    plt.title("$t_{max} = " + str(t_max) + "$, et " + str(n) + " particules")
    plt.show()

    print("Theta1 : ")
    print_data(theta1)
    print("\nTheta2:")
    print_data(theta2)

    images, labels = neuralNet.read_image('X.data', 'Y.data', 200)
    new_res = np.where(neuralNet.fitness(theta1, theta2, 1, images) >= 0.5, 1, 0) - np.array(labels)
    new_res = 100 - (np.sum(np.abs(new_res)) / 200) * 100
    print("Accuracy : " + str(new_res) + "%")

def ten_times(boolean):
    """Lance 10 fois l'algorithme PSO

    On va lancer 10 fois l'algorithme, en récupérant la fitness du best à chaque fois.
    On print ces valeurs
    """
    n = 30
    liste = []
    res2 = []
    vmax = 0.3
    for x in range(10):
        print("Itération : " + str(x))
        res, _, _ = main(particuleNumbers=n, xPath='X.data', yPath='Y.data', t1=[25, 401],\
         t2=[1, 26], t_max=40, cut_off=boolean, vmax=vmax)
        liste.append(res)

    for ele in liste:
        res2.append(min(ele))
    print(res2)

if __name__ == '__main__':
    plot(True)
    # ten_times(False)
<|endoftext|>


<commit_before># Copyright (c) 2011 Mitch Garnaat http://garnaat.org/
# Copyright (c) 2011 Amazon.com, Inc. or its affiliates.  All Rights Reserved
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish, dis-
# tribute, sublicense, and/or sell copies of the Software, and to permit
# persons to whom the Software is furnished to do so, subject to the fol-
# lowing conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
#
"""
Some utility functions to deal with mapping Amazon DynamoDB types to
Python types and vice-versa.
"""
import base64
from decimal import (Decimal, DecimalException, Context,
                     Clamped, Overflow, Inexact, Underflow, Rounded)
from exceptions import DynamoDBNumberError

DYNAMODB_CONTEXT = Context(
    Emin=-128, Emax=126, rounding=None, prec=38,
    traps=[Clamped, Overflow, Inexact, Rounded, Underflow])

# python2.6 cannot convert floats directly to
# Decimals.  This is taken from:
# http://docs.python.org/release/2.6.7/library/decimal.html#decimal-faq
def float_to_decimal(f):
    n, d = f.as_integer_ratio()
    numerator, denominator = Decimal(n), Decimal(d)
    ctx = DYNAMODB_CONTEXT
    result = ctx.divide(numerator, denominator)
    while ctx.flags[Inexact]:
        ctx.flags[Inexact] = False
        ctx.prec *= 2
        result = ctx.divide(numerator, denominator)
    return result

def is_num(n):
    types = (int, long, float, bool, Decimal)
    return isinstance(n, types) or n in types

def is_str(n):
    return isinstance(n, basestring) or (isinstance(n, type) and
                                         issubclass(n, basestring))

def is_binary(n):
    return isinstance(n, Binary)

def serialize_num(val):
    """Cast a number to a string and perform
       validation to ensure no loss of precision.
    """
    if isinstance(val, bool):
        return str(int(val))
    return str(val)

def convert_num(s):
    if '.' in s:
        n = float(s)
    else:
        n = int(s)
    return n

def convert_binary(n):
    return Binary(base64.b64decode(n))

def get_dynamodb_type(val):
    """
    Take a scalar Python value and return a string representing
    the corresponding Amazon DynamoDB type.  If the value passed in is
    not a supported type, raise a TypeError.
    """
    dynamodb_type = None
    if is_num(val):
        dynamodb_type = 'N'
    elif is_str(val):
        dynamodb_type = 'S'
    elif isinstance(val, (set, frozenset)):
        if False not in map(is_num, val):
            dynamodb_type = 'NS'
        elif False not in map(is_str, val):
            dynamodb_type = 'SS'
        elif False not in map(is_binary, val):
            dynamodb_type = 'BS'
    elif isinstance(val, Binary):
        dynamodb_type = 'B'
    if dynamodb_type is None:
        msg = 'Unsupported type "%s" for value "%s"' % (type(val), val)
        raise TypeError(msg)
    return dynamodb_type

def dynamize_value(val):
    """
    Take a scalar Python value and return a dict consisting
    of the Amazon DynamoDB type specification and the value that
    needs to be sent to Amazon DynamoDB.  If the type of the value
    is not supported, raise a TypeError
    """
    dynamodb_type = get_dynamodb_type(val)
    if dynamodb_type == 'N':
        val = {dynamodb_type: serialize_num(val)}
    elif dynamodb_type == 'S':
        val = {dynamodb_type: val}
    elif dynamodb_type == 'NS':
        val = {dynamodb_type: map(serialize_num, val)}
    elif dynamodb_type == 'SS':
        val = {dynamodb_type: [n for n in val]}
    elif dynamodb_type == 'B':
        val = {dynamodb_type: val.encode()}
    elif dynamodb_type == 'BS':
        val = {dynamodb_type: [n.encode() for n in val]}
    return val

class Binary(object):
    def __init__(self, value):
        self.value = value

    def encode(self):
        return base64.b64encode(self.value)

    def __eq__(self, other):
        if isinstance(other, Binary):
            return self.value == other.value
        else:
            return self.value == other

    def __ne__(self, other):
        return not self.__eq__(other)

    def __repr__(self):
        return 'Binary(%s)' % self.value

    def __str__(self):
        return self.value

    def __hash__(self):
        return hash(self.value)

def item_object_hook(dct):
    """
    A custom object hook for use when decoding JSON item bodys.
    This hook will transform Amazon DynamoDB JSON responses to something
    that maps directly to native Python types.
    """
    if len(dct.keys()) > 1:
        return dct
    if 'S' in dct:
        return dct['S']
    if 'N' in dct:
        return convert_num(dct['N'])
    if 'SS' in dct:
        return set(dct['SS'])
    if 'NS' in dct:
        return set(map(convert_num, dct['NS']))
    if 'B' in dct:
        return convert_binary(dct['B'])
    if 'BS' in dct:
        return set(map(convert_binary, dct['BS']))
    return dct

class Dynamizer(object):
    """Control serialization/deserialization of types.

    This class controls the encoding of python types to the
    format that is expected by the DynamoDB API, as well as
    taking DynamoDB types and constructing the appropriate
    python types.

    If you want to customize this process, you can subclass
    this class and override the encoding/decoding of
    specific types.  For example::

        'foo'      (Python type)
            |
            v
        encode('foo')
            |
            v
        _encode_s('foo')
            |
            v
        {'S': 'foo'}  (Encoding sent to/received from DynamoDB)
            |
            V
        decode({'S': 'foo'})
            |
            v
        _decode_s({'S': 'foo'})
            |
            v
        'foo'     (Python type)

    """
    def _get_dynamodb_type(self, attr):
        return get_dynamodb_type(attr)

    def encode(self, attr):
        """
        Encodes a python type to the format expected
        by DynamoDB.

        """
        dynamodb_type = self._get_dynamodb_type(attr)
        try:
            encoder = getattr(self, '_encode_%s' % dynamodb_type.lower())
        except AttributeError:
            raise ValueError("Unable to encode dynamodb type: %s" %
                             dynamodb_type)
        return {dynamodb_type: encoder(attr)}

    def _encode_n(self, attr):
        try:
            if isinstance(attr, float) and not hasattr(Decimal, 'from_float'):
                # python2.6 does not support creating Decimals directly
                # from floats so we have to do this ourself.
                n = str(float_to_decimal(attr))
            else:
                n = str(DYNAMODB_CONTEXT.create_decimal(attr))
            if filter(lambda x: x in n, ('Infinity', 'NaN')):
                raise TypeError('Infinity and NaN not supported')
            return n
        except (TypeError, DecimalException), e:
            msg = '{0} numeric for `{1}`\n{2}'.format(
                e.__class__.__name__, attr, str(e) or '')
        raise DynamoDBNumberError(msg)

    def _encode_s(self, attr):
        return str(attr)

    def _encode_ns(self, attr):
        return map(self._encode_n, attr)

    def _encode_ss(self, attr):
        return [self._encode_s(n) for n in attr]

    def _encode_b(self, attr):
        return attr.encode()

    def _encode_bs(self, attr):
        return [self._encode_b(n) for n in attr]

    def decode(self, attr):
        """
        Takes the format returned by DynamoDB and constructs
        the appropriate python type.

        """
        if len(attr) > 1 or not attr:
            return attr
        dynamodb_type = attr.keys()[0]
        try:
            decoder = getattr(self, '_decode_%s' % dynamodb_type.lower())
        except AttributeError:
            return attr
        return decoder(attr[dynamodb_type])

    def _decode_n(self, attr):
        return DYNAMODB_CONTEXT.create_decimal(attr)

    def _decode_s(self, attr):
        return attr

    def _decode_ns(self, attr):
        return set(map(self._decode_n, attr))

    def _decode_ss(self, attr):
        return set(map(self._decode_s, attr))

    def _decode_b(self, attr):
        return convert_binary(attr)

    def _decode_bs(self, attr):
        return set(map(self._decode_b, attr))

class LossyFloatDynamizer(Dynamizer):
    """Use float/int instead of Decimal for numeric types.

    This class is provided for backwards compatibility.  Instead of
    using Decimals for the 'N', 'NS' types it uses ints/floats.

    This class is deprecated and its usage is not encouraged,
    as doing so may result in loss of precision.  Use the
    `Dynamizer` class instead.

    """
    def _encode_n(self, attr):
        return serialize_num(attr)

    def _encode_ns(self, attr):
        return [str(i) for i in attr]

    def _decode_n(self, attr):
        return convert_num(attr)

    def _decode_ns(self, attr):
        return set(map(self._decode_n, attr))
<commit_msg>Fixed dynamodb encode_s function to properly handle unicode/utf-8 encoding.<commit_after># Copyright (c) 2011 Mitch Garnaat http://garnaat.org/
# Copyright (c) 2011 Amazon.com, Inc. or its affiliates.  All Rights Reserved
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish, dis-
# tribute, sublicense, and/or sell copies of the Software, and to permit
# persons to whom the Software is furnished to do so, subject to the fol-
# lowing conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
#
"""
Some utility functions to deal with mapping Amazon DynamoDB types to
Python types and vice-versa.
"""
import base64
from decimal import (Decimal, DecimalException, Context,
                     Clamped, Overflow, Inexact, Underflow, Rounded)
from exceptions import DynamoDBNumberError

DYNAMODB_CONTEXT = Context(
    Emin=-128, Emax=126, rounding=None, prec=38,
    traps=[Clamped, Overflow, Inexact, Rounded, Underflow])

# python2.6 cannot convert floats directly to
# Decimals.  This is taken from:
# http://docs.python.org/release/2.6.7/library/decimal.html#decimal-faq
def float_to_decimal(f):
    n, d = f.as_integer_ratio()
    numerator, denominator = Decimal(n), Decimal(d)
    ctx = DYNAMODB_CONTEXT
    result = ctx.divide(numerator, denominator)
    while ctx.flags[Inexact]:
        ctx.flags[Inexact] = False
        ctx.prec *= 2
        result = ctx.divide(numerator, denominator)
    return result

def is_num(n):
    types = (int, long, float, bool, Decimal)
    return isinstance(n, types) or n in types

def is_str(n):
    return isinstance(n, basestring) or (isinstance(n, type) and
                                         issubclass(n, basestring))

def is_binary(n):
    return isinstance(n, Binary)

def serialize_num(val):
    """Cast a number to a string and perform
       validation to ensure no loss of precision.
    """
    if isinstance(val, bool):
        return str(int(val))
    return str(val)

def convert_num(s):
    if '.' in s:
        n = float(s)
    else:
        n = int(s)
    return n

def convert_binary(n):
    return Binary(base64.b64decode(n))

def get_dynamodb_type(val):
    """
    Take a scalar Python value and return a string representing
    the corresponding Amazon DynamoDB type.  If the value passed in is
    not a supported type, raise a TypeError.
    """
    dynamodb_type = None
    if is_num(val):
        dynamodb_type = 'N'
    elif is_str(val):
        dynamodb_type = 'S'
    elif isinstance(val, (set, frozenset)):
        if False not in map(is_num, val):
            dynamodb_type = 'NS'
        elif False not in map(is_str, val):
            dynamodb_type = 'SS'
        elif False not in map(is_binary, val):
            dynamodb_type = 'BS'
    elif isinstance(val, Binary):
        dynamodb_type = 'B'
    if dynamodb_type is None:
        msg = 'Unsupported type "%s" for value "%s"' % (type(val), val)
        raise TypeError(msg)
    return dynamodb_type

def dynamize_value(val):
    """
    Take a scalar Python value and return a dict consisting
    of the Amazon DynamoDB type specification and the value that
    needs to be sent to Amazon DynamoDB.  If the type of the value
    is not supported, raise a TypeError
    """
    dynamodb_type = get_dynamodb_type(val)
    if dynamodb_type == 'N':
        val = {dynamodb_type: serialize_num(val)}
    elif dynamodb_type == 'S':
        val = {dynamodb_type: val}
    elif dynamodb_type == 'NS':
        val = {dynamodb_type: map(serialize_num, val)}
    elif dynamodb_type == 'SS':
        val = {dynamodb_type: [n for n in val]}
    elif dynamodb_type == 'B':
        val = {dynamodb_type: val.encode()}
    elif dynamodb_type == 'BS':
        val = {dynamodb_type: [n.encode() for n in val]}
    return val

class Binary(object):
    def __init__(self, value):
        self.value = value

    def encode(self):
        return base64.b64encode(self.value)

    def __eq__(self, other):
        if isinstance(other, Binary):
            return self.value == other.value
        else:
            return self.value == other

    def __ne__(self, other):
        return not self.__eq__(other)

    def __repr__(self):
        return 'Binary(%s)' % self.value

    def __str__(self):
        return self.value

    def __hash__(self):
        return hash(self.value)

def item_object_hook(dct):
    """
    A custom object hook for use when decoding JSON item bodys.
    This hook will transform Amazon DynamoDB JSON responses to something
    that maps directly to native Python types.
    """
    if len(dct.keys()) > 1:
        return dct
    if 'S' in dct:
        return dct['S']
    if 'N' in dct:
        return convert_num(dct['N'])
    if 'SS' in dct:
        return set(dct['SS'])
    if 'NS' in dct:
        return set(map(convert_num, dct['NS']))
    if 'B' in dct:
        return convert_binary(dct['B'])
    if 'BS' in dct:
        return set(map(convert_binary, dct['BS']))
    return dct

class Dynamizer(object):
    """Control serialization/deserialization of types.

    This class controls the encoding of python types to the
    format that is expected by the DynamoDB API, as well as
    taking DynamoDB types and constructing the appropriate
    python types.

    If you want to customize this process, you can subclass
    this class and override the encoding/decoding of
    specific types.  For example::

        'foo'      (Python type)
            |
            v
        encode('foo')
            |
            v
        _encode_s('foo')
            |
            v
        {'S': 'foo'}  (Encoding sent to/received from DynamoDB)
            |
            V
        decode({'S': 'foo'})
            |
            v
        _decode_s({'S': 'foo'})
            |
            v
        'foo'     (Python type)

    """
    def _get_dynamodb_type(self, attr):
        return get_dynamodb_type(attr)

    def encode(self, attr):
        """
        Encodes a python type to the format expected
        by DynamoDB.

        """
        dynamodb_type = self._get_dynamodb_type(attr)
        try:
            encoder = getattr(self, '_encode_%s' % dynamodb_type.lower())
        except AttributeError:
            raise ValueError("Unable to encode dynamodb type: %s" %
                             dynamodb_type)
        return {dynamodb_type: encoder(attr)}

    def _encode_n(self, attr):
        try:
            if isinstance(attr, float) and not hasattr(Decimal, 'from_float'):
                # python2.6 does not support creating Decimals directly
                # from floats so we have to do this ourself.
                n = str(float_to_decimal(attr))
            else:
                n = str(DYNAMODB_CONTEXT.create_decimal(attr))
            if filter(lambda x: x in n, ('Infinity', 'NaN')):
                raise TypeError('Infinity and NaN not supported')
            return n
        except (TypeError, DecimalException), e:
            msg = '{0} numeric for `{1}`\n{2}'.format(
                e.__class__.__name__, attr, str(e) or '')
        raise DynamoDBNumberError(msg)

    def _encode_s(self, attr):
        if isinstance(attr, unicode):
            attr = attr.encode('utf-8')
        if not isinstance(attr, str):
            attr = str(attr)
        return attr

    def _encode_ns(self, attr):
        return map(self._encode_n, attr)

    def _encode_ss(self, attr):
        return [self._encode_s(n) for n in attr]

    def _encode_b(self, attr):
        return attr.encode()

    def _encode_bs(self, attr):
        return [self._encode_b(n) for n in attr]

    def decode(self, attr):
        """
        Takes the format returned by DynamoDB and constructs
        the appropriate python type.

        """
        if len(attr) > 1 or not attr:
            return attr
        dynamodb_type = attr.keys()[0]
        try:
            decoder = getattr(self, '_decode_%s' % dynamodb_type.lower())
        except AttributeError:
            return attr
        return decoder(attr[dynamodb_type])

    def _decode_n(self, attr):
        return DYNAMODB_CONTEXT.create_decimal(attr)

    def _decode_s(self, attr):
        return attr

    def _decode_ns(self, attr):
        return set(map(self._decode_n, attr))

    def _decode_ss(self, attr):
        return set(map(self._decode_s, attr))

    def _decode_b(self, attr):
        return convert_binary(attr)

    def _decode_bs(self, attr):
        return set(map(self._decode_b, attr))

class LossyFloatDynamizer(Dynamizer):
    """Use float/int instead of Decimal for numeric types.

    This class is provided for backwards compatibility.  Instead of
    using Decimals for the 'N', 'NS' types it uses ints/floats.

    This class is deprecated and its usage is not encouraged,
    as doing so may result in loss of precision.  Use the
    `Dynamizer` class instead.

    """
    def _encode_n(self, attr):
        return serialize_num(attr)

    def _encode_ns(self, attr):
        return [str(i) for i in attr]

    def _decode_n(self, attr):
        return convert_num(attr)

    def _decode_ns(self, attr):
        return set(map(self._decode_n, attr))
<|endoftext|>


<commit_before># Copyright (c) 2010 Chris Moyer http://coredumped.org/
# All rights reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish, dis-
# tribute, sublicense, and/or sell copies of the Software, and to permit
# persons to whom the Software is furnished to do so, subject to the fol-
# lowing conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.

RECORD_TYPES = ['A', 'AAAA', 'TXT', 'CNAME', 'MX', 'PTR', 'SRV', 'SPF']

from boto.resultset import ResultSet
class ResourceRecordSets(ResultSet):

    ChangeResourceRecordSetsBody = """<?xml version="1.0" encoding="UTF-8"?>
    <ChangeResourceRecordSetsRequest xmlns="https://route53.amazonaws.com/doc/2011-05-05/">
            <ChangeBatch>
                <Comment>%(comment)s</Comment>
                <Changes>%(changes)s</Changes>
            </ChangeBatch>
        </ChangeResourceRecordSetsRequest>"""

    ChangeXML = """<Change>
        <Action>%(action)s</Action>
        %(record)s
    </Change>"""

    def __init__(self, connection=None, hosted_zone_id=None, comment=None):
        self.connection = connection
        self.hosted_zone_id = hosted_zone_id
        self.comment = comment
        self.changes = []
        self.next_record_name = None
        self.next_record_type = None
        ResultSet.__init__(self, [('ResourceRecordSet', Record)])

    def __repr__(self):
        return '<ResourceRecordSets: %s>' % self.hosted_zone_id

    def add_change(self, action, name, type, ttl=600,
            alias_hosted_zone_id=None, alias_dns_name=None, identifier=None,
            weight=None):
        """Add a change request"""
        change = Record(name, type, ttl,
                alias_hosted_zone_id=alias_hosted_zone_id,
                alias_dns_name=alias_dns_name, identifier=identifier,
                weight=weight)
        self.changes.append([action, change])
        return change

    def to_xml(self):
        """Convert this ResourceRecordSet into XML
        to be saved via the ChangeResourceRecordSetsRequest"""
        changesXML = ""
        for change in self.changes:
            changeParams = {"action": change[0], "record": change[1].to_xml()}
            changesXML += self.ChangeXML % changeParams
        params = {"comment": self.comment, "changes": changesXML}
        return self.ChangeResourceRecordSetsBody % params

    def commit(self):
        """Commit this change"""
        if not self.connection:
            import boto
            self.connection = boto.connect_route53()
        return self.connection.change_rrsets(self.hosted_zone_id, self.to_xml())

    def endElement(self, name, value, connection):
        """Overwritten to also add the NextRecordName and
        NextRecordType to the base object"""
        if name == 'NextRecordName':
            self.next_record_name = value
        elif name == 'NextRecordType':
            self.next_record_type = value
        else:
            return ResultSet.endElement(self, name, value, connection)

    def __iter__(self):
        """Override the next function to support paging"""
        results = ResultSet.__iter__(self)
        while results:
            for obj in results:
                yield obj
            if self.is_truncated:
                self.is_truncated = False
                results = self.connection.get_all_rrsets(self.hosted_zone_id, name=self.next_record_name, type=self.next_record_type)
            else:
                results = None

class Record(object):
    """An individual ResourceRecordSet"""

    XMLBody = """<ResourceRecordSet>
        <Name>%(name)s</Name>
        <Type>%(type)s</Type>
        %(weight)s
        %(body)s
    </ResourceRecordSet>"""

    WRRBody = """
        <SetIdentifier>%(identifier)s</SetIdentifier>
        <Weight>%(weight)s</Weight>
    """

    ResourceRecordsBody = """
        <TTL>%(ttl)s</TTL>
        <ResourceRecords>
            %(records)s
        </ResourceRecords>"""

    ResourceRecordBody = """<ResourceRecord>
        <Value>%s</Value>
    </ResourceRecord>"""

    AliasBody = """<AliasTarget>
        <HostedZoneId>%s</HostedZoneId>
        <DNSName>%s</DNSName>
    </AliasTarget>"""

    def __init__(self, name=None, type=None, ttl=600, resource_records=None,
            alias_hosted_zone_id=None, alias_dns_name=None, identifier=None,
            weight=None):
        self.name = name
        self.type = type
        self.ttl = ttl
        if resource_records == None:
            resource_records = []
        self.resource_records = resource_records
        self.alias_hosted_zone_id = alias_hosted_zone_id
        self.alias_dns_name = alias_dns_name
        self.identifier = identifier
        self.weight = weight

    def add_value(self, value):
        """Add a resource record value"""
        self.resource_records.append(value)

    def set_alias(self, alias_hosted_zone_id, alias_dns_name):
        """Make this an alias resource record set"""
        self.alias_hosted_zone_id = alias_hosted_zone_id
        self.alias_dns_name = alias_dns_name

    def to_xml(self):
        """Spit this resource record set out as XML"""
        if self.alias_hosted_zone_id != None and self.alias_dns_name != None:
            # Use alias
            body = self.AliasBody % (self.alias_hosted_zone_id, self.alias_dns_name)
        else:
            # Use resource record(s)
            records = ""
            for r in self.resource_records:
                records += self.ResourceRecordBody % r
            body = self.ResourceRecordsBody % {
                "ttl": self.ttl,
                "records": records,
            }
        weight = ""
        if self.identifier != None and self.weight != None:
            weight = self.WRRBody % {"identifier": self.identifier, "weight":
                    self.weight}
        params = {
            "name": self.name,
            "type": self.type,
            "weight": weight,
            "body": body,
        }
        return self.XMLBody % params

    def to_print(self):
        if self.alias_hosted_zone_id != None and self.alias_dns_name != None:
            # Show alias
            return 'ALIAS ' + self.alias_hosted_zone_id + ' ' + self.alias_dns_name
        elif self.identifier != None and self.weight != None:
            return 'WRR %s, %s, %s' % (self.identifier,
                    ",".join(self.resource_records), self.weight)
        else:
            # Show resource record(s)
            return ",".join(self.resource_records)

    def endElement(self, name, value, connection):
        if name == 'Name':
            self.name = value
        elif name == 'Type':
            self.type = value
        elif name == 'TTL':
            self.ttl = value
        elif name == 'Value':
            self.resource_records.append(value)
        elif name == 'HostedZoneId':
            self.alias_hosted_zone_id = value
        elif name == 'DNSName':
            self.alias_dns_name = value
        elif name == 'SetIdentifier':
            self.identifier = value
        elif name == 'Weight':
            self.weight = value

    def startElement(self, name, attrs, connection):
        return None
<commit_msg>Having WRR attributes and a type of alias are not mutually exclusive.<commit_after># Copyright (c) 2010 Chris Moyer http://coredumped.org/
# All rights reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish, dis-
# tribute, sublicense, and/or sell copies of the Software, and to permit
# persons to whom the Software is furnished to do so, subject to the fol-
# lowing conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.

RECORD_TYPES = ['A', 'AAAA', 'TXT', 'CNAME', 'MX', 'PTR', 'SRV', 'SPF']

from boto.resultset import ResultSet
class ResourceRecordSets(ResultSet):

    ChangeResourceRecordSetsBody = """<?xml version="1.0" encoding="UTF-8"?>
    <ChangeResourceRecordSetsRequest xmlns="https://route53.amazonaws.com/doc/2011-05-05/">
            <ChangeBatch>
                <Comment>%(comment)s</Comment>
                <Changes>%(changes)s</Changes>
            </ChangeBatch>
        </ChangeResourceRecordSetsRequest>"""

    ChangeXML = """<Change>
        <Action>%(action)s</Action>
        %(record)s
    </Change>"""

    def __init__(self, connection=None, hosted_zone_id=None, comment=None):
        self.connection = connection
        self.hosted_zone_id = hosted_zone_id
        self.comment = comment
        self.changes = []
        self.next_record_name = None
        self.next_record_type = None
        ResultSet.__init__(self, [('ResourceRecordSet', Record)])

    def __repr__(self):
        return '<ResourceRecordSets: %s>' % self.hosted_zone_id

    def add_change(self, action, name, type, ttl=600,
            alias_hosted_zone_id=None, alias_dns_name=None, identifier=None,
            weight=None):
        """Add a change request"""
        change = Record(name, type, ttl,
                alias_hosted_zone_id=alias_hosted_zone_id,
                alias_dns_name=alias_dns_name, identifier=identifier,
                weight=weight)
        self.changes.append([action, change])
        return change

    def to_xml(self):
        """Convert this ResourceRecordSet into XML
        to be saved via the ChangeResourceRecordSetsRequest"""
        changesXML = ""
        for change in self.changes:
            changeParams = {"action": change[0], "record": change[1].to_xml()}
            changesXML += self.ChangeXML % changeParams
        params = {"comment": self.comment, "changes": changesXML}
        return self.ChangeResourceRecordSetsBody % params

    def commit(self):
        """Commit this change"""
        if not self.connection:
            import boto
            self.connection = boto.connect_route53()
        return self.connection.change_rrsets(self.hosted_zone_id, self.to_xml())

    def endElement(self, name, value, connection):
        """Overwritten to also add the NextRecordName and
        NextRecordType to the base object"""
        if name == 'NextRecordName':
            self.next_record_name = value
        elif name == 'NextRecordType':
            self.next_record_type = value
        else:
            return ResultSet.endElement(self, name, value, connection)

    def __iter__(self):
        """Override the next function to support paging"""
        results = ResultSet.__iter__(self)
        while results:
            for obj in results:
                yield obj
            if self.is_truncated:
                self.is_truncated = False
                results = self.connection.get_all_rrsets(self.hosted_zone_id, name=self.next_record_name, type=self.next_record_type)
            else:
                results = None

class Record(object):
    """An individual ResourceRecordSet"""

    XMLBody = """<ResourceRecordSet>
        <Name>%(name)s</Name>
        <Type>%(type)s</Type>
        %(weight)s
        %(body)s
    </ResourceRecordSet>"""

    WRRBody = """
        <SetIdentifier>%(identifier)s</SetIdentifier>
        <Weight>%(weight)s</Weight>
    """

    ResourceRecordsBody = """
        <TTL>%(ttl)s</TTL>
        <ResourceRecords>
            %(records)s
        </ResourceRecords>"""

    ResourceRecordBody = """<ResourceRecord>
        <Value>%s</Value>
    </ResourceRecord>"""

    AliasBody = """<AliasTarget>
        <HostedZoneId>%s</HostedZoneId>
        <DNSName>%s</DNSName>
    </AliasTarget>"""

    def __init__(self, name=None, type=None, ttl=600, resource_records=None,
            alias_hosted_zone_id=None, alias_dns_name=None, identifier=None,
            weight=None):
        self.name = name
        self.type = type
        self.ttl = ttl
        if resource_records == None:
            resource_records = []
        self.resource_records = resource_records
        self.alias_hosted_zone_id = alias_hosted_zone_id
        self.alias_dns_name = alias_dns_name
        self.identifier = identifier
        self.weight = weight

    def add_value(self, value):
        """Add a resource record value"""
        self.resource_records.append(value)

    def set_alias(self, alias_hosted_zone_id, alias_dns_name):
        """Make this an alias resource record set"""
        self.alias_hosted_zone_id = alias_hosted_zone_id
        self.alias_dns_name = alias_dns_name

    def to_xml(self):
        """Spit this resource record set out as XML"""
        if self.alias_hosted_zone_id != None and self.alias_dns_name != None:
            # Use alias
            body = self.AliasBody % (self.alias_hosted_zone_id, self.alias_dns_name)
        else:
            # Use resource record(s)
            records = ""
            for r in self.resource_records:
                records += self.ResourceRecordBody % r
            body = self.ResourceRecordsBody % {
                "ttl": self.ttl,
                "records": records,
            }
        weight = ""
        if self.identifier != None and self.weight != None:
            weight = self.WRRBody % {"identifier": self.identifier, "weight":
                    self.weight}
        params = {
            "name": self.name,
            "type": self.type,
            "weight": weight,
            "body": body,
        }
        return self.XMLBody % params

    def to_print(self):
        rr = ""
        if self.alias_hosted_zone_id != None and self.alias_dns_name != None:
            # Show alias
            rr = 'ALIAS ' + self.alias_hosted_zone_id + ' ' + self.alias_dns_name
        else:
            # Show resource record(s)
            rr =  ",".join(self.resource_records)

        if self.identifier != None and self.weight != None:
            rr += ' (WRR id=%s, w=%s)' % (self.identifier, self.weight)

        return rr

    def endElement(self, name, value, connection):
        if name == 'Name':
            self.name = value
        elif name == 'Type':
            self.type = value
        elif name == 'TTL':
            self.ttl = value
        elif name == 'Value':
            self.resource_records.append(value)
        elif name == 'HostedZoneId':
            self.alias_hosted_zone_id = value
        elif name == 'DNSName':
            self.alias_dns_name = value
        elif name == 'SetIdentifier':
            self.identifier = value
        elif name == 'Weight':
            self.weight = value

    def startElement(self, name, attrs, connection):
        return None
<|endoftext|>


<commit_before># tsl2591 lux sensor interface
import time

VISIBLE = 2
INFRARED = 1
FULLSPECTRUM = 0

ADDR = 0x29
READBIT = 0x01
COMMAND_BIT = 0xA0
CLEAR_BIT = 0x40
WORD_BIT = 0x20
BLOCK_BIT = 0x10
ENABLE_POWERON = 0x01
ENABLE_POWEROFF = 0x00
ENABLE_AEN = 0x02
ENABLE_AIEN = 0x10
CONTROL_RESET = 0x80
LUX_DF = 408.0
LUX_COEFB = 1.64
LUX_COEFC = 0.59
LUX_COEFD = 0.86

REGISTER_ENABLE = 0x00
REGISTER_CONTROL = 0x01
REGISTER_THRESHHOLDL_LOW = 0x02
REGISTER_THRESHHOLDL_HIGH = 0x03
REGISTER_THRESHHOLDH_LOW = 0x04
REGISTER_THRESHHOLDH_HIGH = 0x05
REGISTER_INTERRUPT = 0x06
REGISTER_CRC = 0x08
REGISTER_ID = 0x0A
REGISTER_CHAN0_LOW = 0x14
REGISTER_CHAN0_HIGH = 0x15
REGISTER_CHAN1_LOW = 0x16
REGISTER_CHAN1_HIGH = 0x17
INTEGRATIONTIME_100MS = 0x00
INTEGRATIONTIME_200MS = 0x01
INTEGRATIONTIME_300MS = 0x02
INTEGRATIONTIME_400MS = 0x03
INTEGRATIONTIME_500MS = 0x04
INTEGRATIONTIME_600MS = 0x05

GAIN_LOW = 0x00
GAIN_MED = 0x10
GAIN_HIGH = 0x20
GAIN_MAX = 0x30

def _bytes_to_int(data):
    return data[0] + (data[1]<<8)

from machine import I2C, Pin
class SMBusEmulator:
    __slots__ = ('i2c',)
    def __init__(self, scl_pinno=5, sda_pinno=4):
        self.i2c = I2C(scl=Pin(scl_pinno, Pin.IN),
                       sda=Pin(sda_pinno, Pin.IN))

    def write_byte_data(self, addr, cmd, val):
        buf = bytes([cmd, val])
        self.i2c.writeto(addr, buf)

    def read_word_data(self, addr, cmd):
        assert cmd < 256
        buf = bytes([cmd])
        self.i2c.writeto(addr, buf)
        data = self.i2c.readfrom(addr, 4)
        return _bytes_to_int(data)

SENSOR_ADDRESS=0x29

class Tsl2591:
    def __init__(
                 self,
                 integration=INTEGRATIONTIME_100MS,
                 gain=GAIN_LOW
                 ):
        self.bus = SMBusEmulator()
        self.integration_time = integration
        self.gain = gain
        self.set_timing(self.integration_time)
        self.set_gain(self.gain)
        self.disable()

    def set_timing(self, integration):
        self.enable()
        self.integration_time = integration
        self.bus.write_byte_data(
                    SENSOR_ADDRESS,
                    COMMAND_BIT | REGISTER_CONTROL,
                    self.integration_time | self.gain
                    )
        self.disable()

    def set_gain(self, gain):
        self.enable()
        self.gain = gain
        self.bus.write_byte_data(
                    SENSOR_ADDRESS,
                    COMMAND_BIT | REGISTER_CONTROL,
                    self.integration_time | self.gain
                    )
        self.disable()

    def calculate_lux(self, full, ir):
        if (full == 0xFFFF) | (ir == 0xFFFF):
            return 0

        case_integ = {
            INTEGRATIONTIME_100MS: 100.,
            INTEGRATIONTIME_200MS: 200.,
            INTEGRATIONTIME_300MS: 300.,
            INTEGRATIONTIME_400MS: 400.,
            INTEGRATIONTIME_500MS: 500.,
            INTEGRATIONTIME_600MS: 600.,
            }
        if self.integration_time in case_integ.keys():
            atime = case_integ[self.integration_time]
        else:
            atime = 100.

        case_gain = {
            GAIN_LOW: 1.,
            GAIN_MED: 25.,
            GAIN_HIGH: 428.,
            GAIN_MAX: 9876.,
            }

        if self.gain in case_gain.keys():
            again = case_gain[self.gain]
        else:
            again = 1.

        cpl = (atime * again) / LUX_DF
        lux1 = (full - (LUX_COEFB * ir)) / cpl

        lux2 = ((LUX_COEFC * full) - (LUX_COEFD * ir)) / cpl

        return max([lux1, lux2])

    def enable(self):
        self.bus.write_byte_data(
                    SENSOR_ADDRESS,
                    COMMAND_BIT | REGISTER_ENABLE,
                    ENABLE_POWERON | ENABLE_AEN | ENABLE_AIEN
                    )

    def disable(self):
        self.bus.write_byte_data(
                    SENSOR_ADDRESS,
                    COMMAND_BIT | REGISTER_ENABLE,
                    ENABLE_POWEROFF
                    )

    def get_full_luminosity(self):
        self.enable()
        time.sleep(0.120*self.integration_time+1)
        full = self.bus.read_word_data(
                    SENSOR_ADDRESS, COMMAND_BIT | REGISTER_CHAN0_LOW
                    )
        ir = self.bus.read_word_data(
                    SENSOR_ADDRESS, COMMAND_BIT | REGISTER_CHAN1_LOW
                    )
        self.disable()
        return full, ir

    def get_luminosity(self, channel):
        full, ir = self.get_full_luminosity()
        if channel == FULLSPECTRUM:
            return full
        elif channel == INFRARED:
            return ir
        elif channel == VISIBLE:
            return full - ir
        else:
            return 0

    def sample(self):
        full, ir = self.get_full_luminosity()
        return self.calculate_lux(full, ir)

<commit_msg>Now, the sensor object takes a "sensor_id" parameter<commit_after># tsl2591 lux sensor interface
import time

VISIBLE = 2
INFRARED = 1
FULLSPECTRUM = 0

ADDR = 0x29
READBIT = 0x01
COMMAND_BIT = 0xA0
CLEAR_BIT = 0x40
WORD_BIT = 0x20
BLOCK_BIT = 0x10
ENABLE_POWERON = 0x01
ENABLE_POWEROFF = 0x00
ENABLE_AEN = 0x02
ENABLE_AIEN = 0x10
CONTROL_RESET = 0x80
LUX_DF = 408.0
LUX_COEFB = 1.64
LUX_COEFC = 0.59
LUX_COEFD = 0.86

REGISTER_ENABLE = 0x00
REGISTER_CONTROL = 0x01
REGISTER_THRESHHOLDL_LOW = 0x02
REGISTER_THRESHHOLDL_HIGH = 0x03
REGISTER_THRESHHOLDH_LOW = 0x04
REGISTER_THRESHHOLDH_HIGH = 0x05
REGISTER_INTERRUPT = 0x06
REGISTER_CRC = 0x08
REGISTER_ID = 0x0A
REGISTER_CHAN0_LOW = 0x14
REGISTER_CHAN0_HIGH = 0x15
REGISTER_CHAN1_LOW = 0x16
REGISTER_CHAN1_HIGH = 0x17
INTEGRATIONTIME_100MS = 0x00
INTEGRATIONTIME_200MS = 0x01
INTEGRATIONTIME_300MS = 0x02
INTEGRATIONTIME_400MS = 0x03
INTEGRATIONTIME_500MS = 0x04
INTEGRATIONTIME_600MS = 0x05

GAIN_LOW = 0x00
GAIN_MED = 0x10
GAIN_HIGH = 0x20
GAIN_MAX = 0x30

def _bytes_to_int(data):
    return data[0] + (data[1]<<8)

from machine import I2C, Pin
class SMBusEmulator:
    __slots__ = ('i2c',)
    def __init__(self, scl_pinno=5, sda_pinno=4):
        self.i2c = I2C(scl=Pin(scl_pinno, Pin.IN),
                       sda=Pin(sda_pinno, Pin.IN))

    def write_byte_data(self, addr, cmd, val):
        buf = bytes([cmd, val])
        self.i2c.writeto(addr, buf)

    def read_word_data(self, addr, cmd):
        assert cmd < 256
        buf = bytes([cmd])
        self.i2c.writeto(addr, buf)
        data = self.i2c.readfrom(addr, 4)
        return _bytes_to_int(data)

SENSOR_ADDRESS=0x29

class Tsl2591:
    def __init__(
                 self,
                 sensor_id,
                 integration=INTEGRATIONTIME_100MS,
                 gain=GAIN_LOW
                 ):
        self.sensor_id = sensor_id
        self.bus = SMBusEmulator()
        self.integration_time = integration
        self.gain = gain
        self.set_timing(self.integration_time)
        self.set_gain(self.gain)
        self.disable()

    def set_timing(self, integration):
        self.enable()
        self.integration_time = integration
        self.bus.write_byte_data(
                    SENSOR_ADDRESS,
                    COMMAND_BIT | REGISTER_CONTROL,
                    self.integration_time | self.gain
                    )
        self.disable()

    def set_gain(self, gain):
        self.enable()
        self.gain = gain
        self.bus.write_byte_data(
                    SENSOR_ADDRESS,
                    COMMAND_BIT | REGISTER_CONTROL,
                    self.integration_time | self.gain
                    )
        self.disable()

    def calculate_lux(self, full, ir):
        if (full == 0xFFFF) | (ir == 0xFFFF):
            return 0

        case_integ = {
            INTEGRATIONTIME_100MS: 100.,
            INTEGRATIONTIME_200MS: 200.,
            INTEGRATIONTIME_300MS: 300.,
            INTEGRATIONTIME_400MS: 400.,
            INTEGRATIONTIME_500MS: 500.,
            INTEGRATIONTIME_600MS: 600.,
            }
        if self.integration_time in case_integ.keys():
            atime = case_integ[self.integration_time]
        else:
            atime = 100.

        case_gain = {
            GAIN_LOW: 1.,
            GAIN_MED: 25.,
            GAIN_HIGH: 428.,
            GAIN_MAX: 9876.,
            }

        if self.gain in case_gain.keys():
            again = case_gain[self.gain]
        else:
            again = 1.

        cpl = (atime * again) / LUX_DF
        lux1 = (full - (LUX_COEFB * ir)) / cpl

        lux2 = ((LUX_COEFC * full) - (LUX_COEFD * ir)) / cpl

        return max([lux1, lux2])

    def enable(self):
        self.bus.write_byte_data(
                    SENSOR_ADDRESS,
                    COMMAND_BIT | REGISTER_ENABLE,
                    ENABLE_POWERON | ENABLE_AEN | ENABLE_AIEN
                    )

    def disable(self):
        self.bus.write_byte_data(
                    SENSOR_ADDRESS,
                    COMMAND_BIT | REGISTER_ENABLE,
                    ENABLE_POWEROFF
                    )

    def get_full_luminosity(self):
        self.enable()
        time.sleep(0.120*self.integration_time+1)
        full = self.bus.read_word_data(
                    SENSOR_ADDRESS, COMMAND_BIT | REGISTER_CHAN0_LOW
                    )
        ir = self.bus.read_word_data(
                    SENSOR_ADDRESS, COMMAND_BIT | REGISTER_CHAN1_LOW
                    )
        self.disable()
        return full, ir

    def get_luminosity(self, channel):
        full, ir = self.get_full_luminosity()
        if channel == FULLSPECTRUM:
            return full
        elif channel == INFRARED:
            return ir
        elif channel == VISIBLE:
            return full - ir
        else:
            return 0

    def sample(self):
        full, ir = self.get_full_luminosity()
        return self.calculate_lux(full, ir)

<|endoftext|>


<commit_before><commit_msg>Adding additional logging to help with debugging & support<commit_after><|endoftext|>


<commit_before>from django.contrib import admin
from django import forms
from django.template.defaultfilters import slugify

from mptt.forms import TreeNodeChoiceField
from editor.tree_editor import TreeEditor
from genericcollection import GenericCollectionTabularInline

from settings import ALLOW_SLUG_CHANGE, RELATION_MODELS
from categories import registry
from models import Category

class NullTreeNodeChoiceField(forms.ModelChoiceField):
    """A ModelChoiceField for tree nodes."""
    def __init__(self, level_indicator=u'---', *args, **kwargs):
        self.level_indicator = level_indicator
        #kwargs['empty_label'] = None
        super(NullTreeNodeChoiceField, self).__init__(*args, **kwargs)

    def label_from_instance(self, obj):
        """
        Creates labels which represent the tree level of each node when
        generating option labels.
        """
        return u'%s %s' % (self.level_indicator * getattr(obj, obj._meta.level_attr),
                                obj)
if RELATION_MODELS:
    from models import CategoryRelation

    class InlineCategoryRelation(GenericCollectionTabularInline):
        model = CategoryRelation

class CategoryAdminForm(forms.ModelForm):
    parent = NullTreeNodeChoiceField(queryset=Category.tree.all(),
                                 level_indicator=u'+-',
                                 empty_label='------',
                                 required=False)
    class Meta:
        model = Category

    def clean_slug(self):
        if self.instance is None or not ALLOW_SLUG_CHANGE:
            self.cleaned_data['slug'] = slugify(self.cleaned_data['name'])
        return self.cleaned_data['slug']

    def clean_alternate_title(self):
        if self.instance is None or not self.cleaned_data['alternate_title']:
            return self.cleaned_data['name']
        else:
            return self.cleaned_data['alternate_title']

    def clean(self):
        super(CategoryAdminForm, self).clean()

        # Validate slug is valid in that level
        kwargs = {}
        if self.cleaned_data.get('parent', None) is None:
            kwargs['parent__isnull'] = True
        else:
            kwargs['parent__pk'] = int(self.cleaned_data['parent'].id)
        this_level_slugs = [c['slug'] for c in Category.objects.filter(**kwargs).values('id','slug') if c['id'] != self.instance.id]
        if self.cleaned_data['slug'] in this_level_slugs:
            raise forms.ValidationError("A category slug must be unique among categories at its level.")

        # Validate Category Parent
        # Make sure the category doesn't set itself or any of its children as its parent."
        if self.cleaned_data.get('parent', None) is None or self.instance.id is None:
            return self.cleaned_data
        elif self.cleaned_data['parent'].id == self.instance.id:
            raise forms.ValidationError("You can't set the parent of the category to itself.")
        elif self.cleaned_data['parent'].id in [i[0] for i in self.instance.get_descendants().values_list('id')]:
            raise forms.ValidationError("You can't set the parent of the category to a descendant.")
        return self.cleaned_data

class CategoryAdmin(TreeEditor, admin.ModelAdmin):
    form = CategoryAdminForm
    list_display = ('__unicode__',)
    search_fields = (('name',))
    prepopulated_fields = {'slug': ('name',)}
    fieldsets = (
        (None, {
            'fields': ('parent', 'name')
        }),
        ('Meta Data', {
            'fields': ('alternate_title', 'description', 'meta_keywords', 'meta_extra'),
            'classes': ('collapse',),
        }),
        ('Advanced', {
            'fields': ('order', 'slug'),
            'classes': ('collapse',),
        }),
    )
    if RELATION_MODELS:
        inlines = [InlineCategoryRelation,]

    class Media:
        js = ('js/genericcollections.js',)

admin.site.register(Category, CategoryAdmin)

for model,modeladmin in admin.site._registry.items():
    if model in registry.values():
        admin.site.unregister(model)
        admin.site.register(model, type('newadmin', (modeladmin.__class__,), {
            'fieldsets': getattr(modeladmin, 'fieldsets', ()) + (('Categories',{
                'fields': ('category','categories'),
            }),)
        }))<commit_msg>Fixing bug #6 per primski. Adds the correct fields into the admin instead of both.<commit_after>from django.contrib import admin
from django import forms
from django.template.defaultfilters import slugify

from mptt.forms import TreeNodeChoiceField
from editor.tree_editor import TreeEditor
from genericcollection import GenericCollectionTabularInline

from settings import ALLOW_SLUG_CHANGE, RELATION_MODELS
from categories import registry
from models import Category

class NullTreeNodeChoiceField(forms.ModelChoiceField):
    """A ModelChoiceField for tree nodes."""
    def __init__(self, level_indicator=u'---', *args, **kwargs):
        self.level_indicator = level_indicator
        #kwargs['empty_label'] = None
        super(NullTreeNodeChoiceField, self).__init__(*args, **kwargs)

    def label_from_instance(self, obj):
        """
        Creates labels which represent the tree level of each node when
        generating option labels.
        """
        return u'%s %s' % (self.level_indicator * getattr(obj, obj._meta.level_attr),
                                obj)
if RELATION_MODELS:
    from models import CategoryRelation

    class InlineCategoryRelation(GenericCollectionTabularInline):
        model = CategoryRelation

class CategoryAdminForm(forms.ModelForm):
    parent = NullTreeNodeChoiceField(queryset=Category.tree.all(),
                                 level_indicator=u'+-',
                                 empty_label='------',
                                 required=False)
    class Meta:
        model = Category

    def clean_slug(self):
        if self.instance is None or not ALLOW_SLUG_CHANGE:
            self.cleaned_data['slug'] = slugify(self.cleaned_data['name'])
        return self.cleaned_data['slug']

    def clean_alternate_title(self):
        if self.instance is None or not self.cleaned_data['alternate_title']:
            return self.cleaned_data['name']
        else:
            return self.cleaned_data['alternate_title']

    def clean(self):
        super(CategoryAdminForm, self).clean()

        # Validate slug is valid in that level
        kwargs = {}
        if self.cleaned_data.get('parent', None) is None:
            kwargs['parent__isnull'] = True
        else:
            kwargs['parent__pk'] = int(self.cleaned_data['parent'].id)
        this_level_slugs = [c['slug'] for c in Category.objects.filter(**kwargs).values('id','slug') if c['id'] != self.instance.id]
        if self.cleaned_data['slug'] in this_level_slugs:
            raise forms.ValidationError("A category slug must be unique among categories at its level.")

        # Validate Category Parent
        # Make sure the category doesn't set itself or any of its children as its parent."
        if self.cleaned_data.get('parent', None) is None or self.instance.id is None:
            return self.cleaned_data
        elif self.cleaned_data['parent'].id == self.instance.id:
            raise forms.ValidationError("You can't set the parent of the category to itself.")
        elif self.cleaned_data['parent'].id in [i[0] for i in self.instance.get_descendants().values_list('id')]:
            raise forms.ValidationError("You can't set the parent of the category to a descendant.")
        return self.cleaned_data

class CategoryAdmin(TreeEditor, admin.ModelAdmin):
    form = CategoryAdminForm
    list_display = ('__unicode__',)
    search_fields = (('name',))
    prepopulated_fields = {'slug': ('name',)}
    fieldsets = (
        (None, {
            'fields': ('parent', 'name')
        }),
        ('Meta Data', {
            'fields': ('alternate_title', 'description', 'meta_keywords', 'meta_extra'),
            'classes': ('collapse',),
        }),
        ('Advanced', {
            'fields': ('order', 'slug'),
            'classes': ('collapse',),
        }),
    )
    if RELATION_MODELS:
        inlines = [InlineCategoryRelation,]

    class Media:
        js = ('js/genericcollections.js',)

admin.site.register(Category, CategoryAdmin)

for model,modeladmin in admin.site._registry.items():
    if model in registry.values():
        admin.site.unregister(model)
        admin.site.register(model, type('newadmin', (modeladmin.__class__,), {
            'fieldsets': getattr(modeladmin, 'fieldsets', ()) + (('Categories',{
                'fields': [cat.split('.')[1] for cat in registry]
            }),)
        }))<|endoftext|>


<commit_before># Feel free to modify and use this filter however you wish. If you do,
# please give credit to SethBling.
# http://youtube.com/SethBling
#
''' Fixed for MC 1.8 by Rezzing, September 6, 2014
PLEASE READ: The unusable trade won't prevent new trades anymore but I
solved it by adding a very high career level. So only use it if you like
the fancy stop sign. '''
# Reedited by DragonQuiz, November 7, 2014
#
# Changes: ^denotes new change
# 1) Allow your villager to move or not.
# 2) Rename your villager in MCEdit.
# 3) Allow players to receive experience for their trade.
# 4) Updated more of the code, made it much prettier.
''' 5) Added rotation so the villager *can rotate* when possible. Currently Broken'''
# And a big thanks to Sethbling for creating this filter and all his other filters at http://sethbling.com/downloads/mcedit-filters/

from pymclevel import TAG_Byte, TAG_Short, TAG_Int, TAG_Compound, TAG_List, TAG_String, TAG_Double, TAG_Float

displayName = "Create Shops"

Professions = {
	"Farmer (brown)": 0,
	"Librarian (white)": 1,
	"Priest (purple)": 2,
	"Blacksmith (black apron)": 3,
	"Butcher (white apron)": 4,
	"Villager (green)": 5,
	}

ProfessionKeys = ()
for key in Professions.keys():
	ProfessionKeys = ProfessionKeys + (key,)

inputs = [( ("General Trade","title"),
	("This is a modified version of SethBling's Create Shops filter at DragonQuiz's request","label"),
	("Profession", ProfessionKeys),
	("Add Stopping Trade", True),
	("Invulnerable Villager", True),
	("Make Unlimited Trades", True),
	("Give Experience per a Trade", True),
	("Make Villager not Move", False),
	("Villager Name",("string","width=250")),),

	#(("Rotation","title"),
	#("*May or May not work, did work in testing(sometimes)*","label"),
	#("      Rotate the Position of your Trader\n"
	#"*Can only be used if Not Move is checked*","label"),
	#("Y-Axis",(0, 360)),
	#("Changes its body rotation. Due west is 0. Must be less than 360 degrees.","label"),
	#("X-Axis",("string","width=50")),
	#("Changes the head rotation Horizontal is 0. Positive values look downward. Less than +/- 90 degrees","label"),
	#),

	(("Trade Notes","title"),
	("To create a shop first put your buy in the top slot(s) of the chest.\n"
	"Second put a second buy in the middle slot(optional).\n"
	"Third put a sell in the bottom slot.\n"
	"Click the chest you want and choose what you want and click hit enter\n"
	"*All items must be in the same row*\n"
	"\n"
	"Advanced, little experience in notepad ++ is recommended.\n"
	"To change the amount of trades:\n"
	"1) Uncheck 'Unlimited Trades'\n"
	"2) Open the createshops filter using Notepad++ (link:http://notepad-plus-plus.org/) or notepad\n"
	"*The filter is where you put the MCEdit folder*\n"
	"3) Scroll to:\n"
	            "else:\n"
				"offer[uses] = TAG_Int(0)\n"
				"offer[maxUses] = TAG_Int(1)\n"
	"4) Change the amount you want\n"
	"\n"
	"*Note: Only change the numbers as above, changing anything else will result in the filter to not work correctly*\n"
	,"label")),
	]

def perform(level, box, options):
	emptyTrade = options["Add Stopping Trade"]
	invincible = options["Invulnerable Villager"]
	unlimited = options["Make Unlimited Trades"]
	xp = options["Give Experience per a Trade"]
	nomove = options["Make Villager not Move"]
	name = options["Villager Name"]
	#yaxis = options["Y-Axis"]
	#xaxis = options["X-Axis"]
	for (chunk, slices, point) in level.getChunkSlices(box):
		for e in chunk.TileEntities:
			x = e["x"].value
			y = e["y"].value
			z = e["z"].value

			if (x,y,z) in box:
				if e["id"].value == "Chest":
					createShop(level, x, y, z, emptyTrade, invincible, Professions[options["Profession"]], unlimited, xp, nomove, name)

def createShop(level, x, y, z, emptyTrade, invincible, profession, unlimited, xp, nomove, name):
	chest = level.tileEntityAt(x, y, z)
	if chest == None:
		return

	priceList = {}
	priceListB = {}
	saleList = {}

	for item in chest["Items"]:
		slot = item["Slot"].value
		if slot >= 0 and slot <= 8:
			priceList[slot] = item
		elif slot >= 9 and slot <= 17:
			priceListB[slot-9] = item
		elif slot >= 18 and slot <= 26:
			saleList[slot-18] = item

	villager = TAG_Compound()
	villager["PersistenceRequired"] = TAG_Byte(1)
	villager["OnGround"] = TAG_Byte(1)
	villager["Air"] = TAG_Short(300)
	villager["AttackTime"] = TAG_Short(0)
	villager["DeathTime"] = TAG_Short(0)
	villager["Fire"] = TAG_Short(-1)
	villager["Health"] = TAG_Short(20)
	villager["HurtTime"] = TAG_Short(0)
	villager["Age"] = TAG_Int(0)
	villager["Profession"] = TAG_Int(profession)
	villager["Career"] = TAG_Int(1)
	villager["CareerLevel"] = TAG_Int(1000)
	villager["Riches"] = TAG_Int(200)
	villager["FallDistance"] = TAG_Float(0)
	villager["CustomNameVisible"] = TAG_Byte(1)
	villager["CustomName"] = TAG_String(name)
	villager["Invulnerable"] = TAG_Byte(invincible)
	villager["NoAI"] = TAG_Byte(nomove)
	villager["id"] = TAG_String("Villager")
	villager["Motion"] = TAG_List([TAG_Double(0.0), TAG_Double(0.0), TAG_Double(0.0)])
	villager["Pos"] = TAG_List ([TAG_Double(x + 0.5), TAG_Double(y), TAG_Double(z + 0.5)])
	villager["Rotation"] = TAG_List([TAG_Float(0), TAG_Float(0)])

	villager["Willing"] = TAG_Byte(0)
	villager["Offers"] = TAG_Compound()
	villager["Offers"]["Recipes"] = TAG_List()
	for i in range(9):
		if (i in priceList or i in priceListB) and i in saleList:
			offer = TAG_Compound()
			if xp:
				offer["rewardExp"] = TAG_Byte(1)
			else:
				offer["rewardExp"] = TAG_Byte(0)

			if unlimited:
				offer["uses"] = TAG_Int(0)
				offer["maxUses"] = TAG_Int(2000000000)
			else:
				offer["uses"] = TAG_Int(0)
				offer["maxUses"] = TAG_Int(1)

			if i in priceList:
				offer["buy"] = priceList[i]
			if i in priceListB:
				if i in priceList:
					offer["buyB"] = priceListB[i]
				else:
					offer["buy"] = priceListB[i]

			offer["sell"] = saleList[i]
			villager["Offers"]["Recipes"].append(offer)

	if emptyTrade:
		offer = TAG_Compound()
		offer["buy"] = TAG_Compound()
		offer["buy"]["Count"] = TAG_Byte(1)
		offer["buy"]["Damage"] = TAG_Short(0)
		offer["buy"]["id"] = TAG_String("minecraft:barrier")
		offer["sell"] = TAG_Compound()
		offer["sell"]["Count"] = TAG_Byte(1)
		offer["sell"]["Damage"] = TAG_Short(0)
		offer["sell"]["id"] = TAG_String("minecraft:barrier")
		villager["Offers"]["Recipes"].append(offer)

	level.setBlockAt(x, y, z, 0)

	chunk = level.getChunk(x / 16, z / 16)
	chunk.Entities.append(villager)
	chunk.TileEntities.remove(chest)
	chunk.dirty = True
<commit_msg>Fixed CreateShops filter<commit_after># Feel free to modify and use this filter however you wish. If you do,
# please give credit to SethBling.
# http://youtube.com/SethBling
#
''' Fixed for MC 1.8 by Rezzing, September 6, 2014
PLEASE READ: The unusable trade won't prevent new trades anymore but I
solved it by adding a very high career level. So only use it if you like
the fancy stop sign. '''
# Reedited by DragonQuiz, November 8, 2014
#
# Changes: ^denotes new change
# 1) Allow your villager to move or not.
# 2) Rename your villager in MCEdit.
# 3) Allow players to receive experience for their trade.
# 4) Updated more of the code, made it much prettier.
# 5) Added rotation so the villager *can rotate* when possible.
# And a big thanks to Sethbling for creating this filter and all his other filters at http://sethbling.com/downloads/mcedit-filters/

from pymclevel import TAG_Byte, TAG_Short, TAG_Int, TAG_Compound, TAG_List, TAG_String, TAG_Double, TAG_Float

displayName = "Create Shops"

Professions = {
	"Farmer (brown)": 0,
	"Librarian (white)": 1,
	"Priest (purple)": 2,
	"Blacksmith (black apron)": 3,
	"Butcher (white apron)": 4,
	"Villager (green)": 5,
	}

ProfessionKeys = ()
for key in Professions.keys():
	ProfessionKeys = ProfessionKeys + (key,)

inputs = [( ("General Trade","title"),
	("This is a modified version of SethBling's Create Shops filter at DragonQuiz's request","label"),
	("Profession", ProfessionKeys),
	("Add Stopping Trade", True),
	("Invulnerable Villager", True),
	("Make Unlimited Trades", True),
	("Give Experience per a Trade", True),
	("Make Villager not Move", False),
	("Villager Name",("string","width=250")),),

	(("Rotation","title"),
	("      Rotate the Position of your Trader\n"
	"*Can only be used if Not Move is checked*","label"),
	("Y-Axis",(0, -180, 180)),
	("Changes its body rotation. Due west is 0. Must be between -180 to 180 degrees.","label"),
	("X-Axis",(0, -90, 90)),
	("Changes the head rotation Horizontal is 0. Positive values look downward. Must be between -90 to 90 degrees","label"),
	),

	(("Trade Notes","title"),
	("To create a shop first put your buy in the top slot(s) of the chest.\n"
	"Second put a second buy in the middle slot(optional).\n"
	"Third put a sell in the bottom slot.\n"
	"Click the chest you want and choose what you want and click hit enter\n"
	"*All items must be in the same row*\n"
	"\n"
	"Advanced, little experience in notepad ++ is recommended.\n"
	"To change the amount of trades:\n"
	"1) Uncheck 'Unlimited Trades'\n"
	"2) Open the createshops filter using Notepad++ (link:http://notepad-plus-plus.org/) or notepad\n"
	"*The filter is where you put the MCEdit folder*\n"
	"3) Scroll to:\n"
	            "else:\n"
				"offer[uses] = TAG_Int(0)\n"
				"offer[maxUses] = TAG_Int(1)\n"
	"4) Change the amount you want\n"
	"\n"
	"*Note: Only change the numbers as above, changing anything else will result in the filter to not work correctly*\n"
	,"label")),
	]

def perform(level, box, options):
	emptyTrade = options["Add Stopping Trade"]
	invincible = options["Invulnerable Villager"]
	unlimited = options["Make Unlimited Trades"]
	xp = options["Give Experience per a Trade"]
	nomove = options["Make Villager not Move"]
	name = options["Villager Name"]
	yaxis = options["Y-Axis"]
	xaxis = options["X-Axis"]
	for (chunk, slices, point) in level.getChunkSlices(box):
		for e in chunk.TileEntities:
			x = e["x"].value
			y = e["y"].value
			z = e["z"].value

			if (x,y,z) in box:
				if e["id"].value == "Chest":
					createShop(level, x, y, z, emptyTrade, invincible, Professions[options["Profession"]], unlimited, xp, nomove, name, yaxis, xaxis)

def createShop(level, x, y, z, emptyTrade, invincible, profession, unlimited, xp, nomove, name, yaxis, xaxis):
	chest = level.tileEntityAt(x, y, z)
	if chest == None:
		return

	priceList = {}
	priceListB = {}
	saleList = {}

	for item in chest["Items"]:
		slot = item["Slot"].value
		if slot >= 0 and slot <= 8:
			priceList[slot] = item
		elif slot >= 9 and slot <= 17:
			priceListB[slot-9] = item
		elif slot >= 18 and slot <= 26:
			saleList[slot-18] = item

	villager = TAG_Compound()
	villager["PersistenceRequired"] = TAG_Byte(1)
	villager["OnGround"] = TAG_Byte(1)
	villager["Air"] = TAG_Short(300)
	villager["AttackTime"] = TAG_Short(0)
	villager["DeathTime"] = TAG_Short(0)
	villager["Fire"] = TAG_Short(-1)
	villager["Health"] = TAG_Short(20)
	villager["HurtTime"] = TAG_Short(0)
	villager["Age"] = TAG_Int(0)
	villager["Profession"] = TAG_Int(profession)
	villager["Career"] = TAG_Int(1)
	villager["CareerLevel"] = TAG_Int(1000)
	villager["Riches"] = TAG_Int(200)
	villager["FallDistance"] = TAG_Float(0)
	villager["CustomNameVisible"] = TAG_Byte(1)
	villager["CustomName"] = TAG_String(name)
	villager["Invulnerable"] = TAG_Byte(invincible)
	villager["NoAI"] = TAG_Byte(nomove)
	villager["id"] = TAG_String("Villager")
	villager["Motion"] = TAG_List([TAG_Double(0.0), TAG_Double(0.0), TAG_Double(0.0)])
	villager["Pos"] = TAG_List ([TAG_Double(x + 0.5), TAG_Double(y), TAG_Double(z + 0.5)])
	villager["Rotation"] = TAG_List([TAG_Float(yaxis), TAG_Float(xaxis)])

	villager["Willing"] = TAG_Byte(0)
	villager["Offers"] = TAG_Compound()
	villager["Offers"]["Recipes"] = TAG_List()
	for i in range(9):
		if (i in priceList or i in priceListB) and i in saleList:
			offer = TAG_Compound()
			if xp:
				offer["rewardExp"] = TAG_Byte(1)
			else:
				offer["rewardExp"] = TAG_Byte(0)

			if unlimited:
				offer["uses"] = TAG_Int(0)
				offer["maxUses"] = TAG_Int(2000000000)
			else:
				offer["uses"] = TAG_Int(0)
				offer["maxUses"] = TAG_Int(1)

			if i in priceList:
				offer["buy"] = priceList[i]
			if i in priceListB:
				if i in priceList:
					offer["buyB"] = priceListB[i]
				else:
					offer["buy"] = priceListB[i]

			offer["sell"] = saleList[i]
			villager["Offers"]["Recipes"].append(offer)

	if emptyTrade:
		offer = TAG_Compound()
		offer["buy"] = TAG_Compound()
		offer["buy"]["Count"] = TAG_Byte(1)
		offer["buy"]["Damage"] = TAG_Short(0)
		offer["buy"]["id"] = TAG_String("minecraft:barrier")
		offer["sell"] = TAG_Compound()
		offer["sell"]["Count"] = TAG_Byte(1)
		offer["sell"]["Damage"] = TAG_Short(0)
		offer["sell"]["id"] = TAG_String("minecraft:barrier")
		villager["Offers"]["Recipes"].append(offer)

	level.setBlockAt(x, y, z, 0)

	chunk = level.getChunk(x / 16, z / 16)
	chunk.Entities.append(villager)
	chunk.TileEntities.remove(chest)
	chunk.dirty = True
<|endoftext|>