<commit_before>#!python3
# TODO make sure all classes methods have docstrings and full comments
# TODO check all the methods are doing what we think they are (check edge cases etc)
# TODO implement error handling
# TODO? make UML class diagrams

class _Node:
    def __init__(self, key, data=None, freq=None, next_node=None):
        self.key = key
        self.freq = freq
        self.data = data
        self.next_node = next_node

class LinkedList:
    def __init__(self, head=None, tail=None):
        self._head = head
        self._tail = tail
        self._size = 0

    def __iter__(self):
        current = self._head
        while current:
            yield current.key, current.freq
            current = current.next_node

    def __str__(self):
        return " ".join([str(item) for item in self])

    @property
    def head(self):
        return self._head

    @property
    def tail(self):
        return self._tail

    def list_insert_head(self, new_node):  # TODO error handling
        """
        Insert a new node (from an existing node or a key) at the head of the list.
        :param new_node: thing  to be inserted
        """
        if type(new_node) is not _Node:  # if the thing isn't already a node, make it a node
            new_node = _Node(new_node)
        new_node.next_node = self._head  # make item point to the current head of the list

        self._head = new_node  # make item be the new head of the list
        if self._size == 0:
            self._tail = self._head
        self._size += 1

    def list_insert_tail(self, new_node):  # add item (key or node) at tail of list, used in mergesort
        """
        Insert a new node at the tail of the list
        :param new_node:  thing to be inserted
        """
        n = self._tail
        if type(new_node) is not _Node:  # if the thing isn't already a node, make it a node
            self._tail = _Node(new_node)
        else:
            self._tail = new_node
        if self._size != 0:
            n.next_node = self.tail  # if this is not the only item
        else:
            self._head = self._tail  # if this is the only item, make it be the first item too
        self._size += 1
        print("selfhead is", self.head.key, "selftail is", self.tail.key)
        return self.head, self.tail

    def list_insert_middle(self, prev, new_node):  # TODO error handling
        """
        Insert a new node, with key *key*, after the node *prev* in the list
        :param prev:  the _Node object to be inserted after
        :param key:  the key of the new node to be inserted
        """
        if type(new_node) is not _Node:
            new_node = _Node(new_node)  # make a node from key (if it is a key)
        new_node.next_node = prev.next_node  # make that node point at what the previous node is currently pointing at
        prev.next_node = new_node  # make the previous node point at the new node
        self._size += 1  # increase size by 1

    def list_delete(self, node):  # TODO error handling
        """
        Delete the specified node from the list, by changing the pointer on the node before to point at the next node.
        :param node: the _Node item you want to delete
        :return: the node you just removed
        """
        prev = self._head  # start at the head of the list
        if prev is not None:  # if there are some items in the list
            # while you haven't matched the node, and there are more nodes to look at
            while prev.next_node != node and prev.next_node is not None:
                prev = prev.next_node  # look at the next one
            if prev.next_node is not None:  # if the node you are looking at when you broke out of the loop has a next
                prev.next_node = node.next_node  # update pointer on prev to point at thing node was pointing at
        self._size -= 1
        return node

    def find_mid(self):  # used in mergesort, returns the middle node of a linked list
        x = self.head
        y = self.head
        while y is not None and y.next_node is not None:
            x = x.next_node
            y = y.next_node.next_node
        return x

    def pop(self):  # remove item at head of list, return it. used in mergesort
        # TODO error handling (empty list)
        n = self._head
        self._head = self._head.next_node
        self._size -= 1
        return n

    def swap_adjacent(self, prev=None):
        """
        Swap the two nodes immediately following the node specified. If prev is None, swap the first two nodes (since
        the head of a list has no previous node)    (so if you specify 7 in 789, you will get 798 with this method)
        :param prev: the node before the pair you want to switch
        :return:
        """
        # TODO error handling (eg when a, b are out of list)
        if prev is None:  # swap first and second items
            a = self.head
            b = self.head.next_node
            a.next_node = b.next_node
            self._head = b
            b.next_node = a
        else:
            a = prev.next_node
            b = prev.next_node.next_node
            a.next_node = b.next_node
            prev.next_node = b
            b.next_node = a
        if a.next_node is None:
            self._tail = a

    def swap(self, before_a, before_b):
        """
        Swap the nodes after the two nodes specified as arguments, by updating the pointers to them
        (If you specify 1 and 4 in 12345, you will get 15342)
        (If two nodes are adjacent, it will swap the two nodes after the first specified node. so 34 in 12345 will be 12354)
        :param before_a: node before the first node you want to swap
        :param before_b: node before the second node you want to swap
        :return: self
        """
        # TODO error handling as above - check a and b exist
        if before_a is None:
            a = self.head
        else:
            a = before_a.next_node
        if a == before_b:  # ie the nodes are adjacent
            self.swap_adjacent(before_a)
            return self

        if before_b is None:
            b = self.head
        else:
            b = before_b.next_node
        before_a.next_node = b
        before_b.next_node = a
        a.next_node, b.next_node = b.next_node, a.next_node
        return self

    def insertionsort(self):
        main = self.head.next_node  # this is the value from the main for loop on a list (start at second item)
        while main is not None:  # while there are still unchecked items in the list
            compare = self.head  # this is the thing from the inner loop on an array, start at the start of the list

            # this while loop will run from the start of the list until you either run out of nodes, or find one bigger than main
            while compare.next_node is not None and compare.next_node.key < main.key:  # there is a node next, and it is still smaller
                compare = compare.next_node  # look at the next one
            if compare.key > main.key:  # this catches the case where main is the smallest element in the list so far and
                                        # needs to be inserted at head of list. This is nasty, could do with being tidied
                move_node = self.list_delete(main)  # cut out main node
                self.list_insert_head(move_node)  # insert it at the head
                main = main.next_node
            else:  # all other cases (compare.key < main.key)
                temp = main
                main = main.next_node
                move_node = self.list_delete(temp)  # cut out the main node
                self.list_insert_middle(compare, move_node)  # insert it after the last node you found that was smaller
                                                               # main and not None

        # update the value of self.tail to be the biggest item!
        start = self.head
        while start.next_node is not None:
            start = start.next_node
        self._tail = start

    def binary_search(self, key):
        """
        Find the key using binary search
        :param key: the key to be found
        :return: node, if not found return None
        """
        self.insertionsort()
        max_i = self._size - 1  # max_i & min_i mark the "boundaries" of the search. now max_i is basically len(list)-1
        min_i = 0
        mid_i = (min_i + max_i)//2
        splitpoint = self.head
        for i in range(min_i, mid_i):  # loop over and find the first middle point (splitpoint)
            splitpoint = splitpoint.next_node  # will loop over and stop at mid_i

        while min_i < max_i and splitpoint.key != key and splitpoint.next_node is not None:
            if splitpoint.key < key:  # key is to the left of splitpoint (reachable with .next_node method)
                min_i = mid_i + 1  # move the left boundary to mid_i (focus on the right part)
                mid_i = (min_i + max_i)//2
                if min_i == max_i:  # when min_i == max_i for i in range won't work, have to change point manually
                # (although we have min_i< max_i in the while loop this is still possible as the loop will not break
                # immediately when min_i == max_i)
                    splitpoint = splitpoint.next_node  # if key is in list it will be this node
                    if splitpoint.key == key: # see if this is the key
                        return splitpoint
                    else:  # if splitpoint != key at this point, key is not in the list
                        return None

                else:  # normal cases, when min_i < max_i
                    for i in range(min_i, mid_i+1):  # will loop over and stop at the new mid_i
                        splitpoint = splitpoint.next_node
                continue  # go back to the start of while loop and see if the new splitpoint is at a reachable position to the key
            # this will break when 1.) when the key is found  2.) when min_i == max_i 3.) splitpoint.next_node is None

            else:  # key is to the right of the splitpoint (unreachable), splitpoint must be reset
                max_i = mid_i  # move the right boundary to mid_i (focus on the left part)
                mid_i = (min_i + max_i) // 2  # get a new mid_i
                splitpoint = self.head  # search for a new splitpoint from the head
                for i in range(0, mid_i):
                    splitpoint = splitpoint.next_node  # will loop over and stop at mid_i
                continue  # go back to the while loop and see if splitpoint < key

        if min_i != max_i:  # if the while loop breaks because splitpoint happens to be the key, it goes here
            return splitpoint
        else:   # if key is smaller than all items in the list, it will loop over the "else" part above and
            return None  # break when min_i == max_i and goes here (no key is found, None is returned)

    def mergesort(self):  # NOTE this sorts on the length of the data attribute
        # This is a method to make the list mergesort itself
        print(self.mergesort_recurse(self))

    def mergesort_recurse(self, lst):  # something weird is happening with the list getting modified... # TODO fix this!
        # this is the main recursive bit of mergesort
        if lst.head is None or lst.head.next_node is None:  # list of 0 or 1 things - trivially sorted
            return lst
        else:
            leftlist = LinkedList(lst.head)  # the left half of the list starts here
            print(leftlist, "leftlist", self._size)
            # find the middle node
            mid = lst.find_mid()
            print(mid.key, "mid-key")
            if mid.next_node is not None:
                rightlist = LinkedList(mid.next_node)
                print(rightlist, "rightlist when mid.next_node is not None")
                mid.next_node = None  # divide the two parts
            else:
                rightlist = LinkedList(mid)
                print(rightlist, "rightlist")
                leftlist.head.next_node = None

            left = self.mergesort_recurse(leftlist)
            right = self.mergesort_recurse(rightlist)
            lst = self.merge(left, right)
            return lst

    @staticmethod
    def merge(l, r):
        # this does the merging bit of mergesort
        merged = LinkedList()
        while l.head is not None or r.head is not None:  # there are items remaining in the left sublist
            print("get to merge now", l, "<- ->", r, "merged is now", merged)
            if l.head is None:  # left sublist is empty
                merged.list_insert_tail(r.pop())  # remove the node at the head of r and push it to the new ll
            elif r.head is None:   # right sublist is empty
                merged.list_insert_tail(l.pop())  # remove the node at the head of l and push to new ll
            else:  # both sublists still have stuff in
                if l.head.key <= r.head.key:  # I fixed this line (it seems that errors come from this, but still not sorting)
                    print(l.head.key, "this is the thing to pop", merged, "<- is merged")
                    # remove the node at the head of l and push to new ll
                    merged.list_insert_tail(l.pop())
                else:  # r.head < l.head
                    merged.list_insert_tail(r.pop())  # remove the node at the head of l and push to new ll
                    print(merged, "after popping from r", merged.tail.key)
        print(merged, "merged")
        return merged

    def quicksort(self):  # note this sorts in reverse order atm, and on the frequ
        print("quicksorting", self)
        return self.quicksort_recurse(self, self.head, self._tail)

    def quicksort_recurse(self, lst, start, end):
        if start and start.key != end.key:
            print("partitioning", start.key, end.key)
            print(self)
            pivot = self.partition(lst, start, end)
            self.quicksort_recurse(lst, start, pivot)
            self.quicksort_recurse(lst, pivot.next_node, end)

    @staticmethod
    def partition(lst, start, end):  # used in quicksort
        pivot = start
        i = pivot
        jprev = pivot  # track the node before j, used for swapping
        j = pivot.next_node
        while j != end.next_node:  # assuming unique keys
            if j.freq > pivot.freq:
                # swap  i and j
                if i.next_node.freq != j.freq:
                    lst.swap(i, jprev)
                i = i.next_node
            jprev = j
            j = j.next_node
        # swap pivot and j  # TODO swap properly!
        pivot.key, i.key = i.key, pivot.key
        pivot.freq, i.freq = i.freq, pivot.freq
        pivot.data, i.data = i.data, pivot.data
        print("pivot {}, i {}".format(pivot.key, i.key))
        return i

    def find(self, key):  # the trivial search algorithm, for testing ngram_list
        node = self.head
        while node:
            if node.key == key:
                return node
            else:
                node = node.next_node
        return None

# TODO error handling generally

if __name__ == "__main__":
    # test code goes here!
    ll = LinkedList()
    lk = LinkedList()
    for i in [5, 2, 9, 8, 1, 3, 6, 7, 14, 45, 15, 20]:
        ll.list_insert_tail(i)
    print(ll)
    #lk.list_insert_tail(ll.pop())
    #print(lk)

    #ll.pop()
    #print(ll)
    ll.mergesort()
    print(ll, "what?", ll._size)

    #ll.binary_search(7)
    #print(ll, "done")
    #ll.swap(ll.binary_search(1), ll.binary_search(4))
    #print(ll, "that's it")
    #print("head {}, tail {}".format(ll.head.key, ll.tail.key))

<commit_msg>I think merge sort is working now :) some comments and print statement removed<commit_after>#!python3
# TODO make sure all classes methods have docstrings and full comments
# TODO check all the methods are doing what we think they are (check edge cases etc)
# TODO implement error handling
# TODO? make UML class diagrams

class _Node:
    def __init__(self, key, data=None, freq=None, next_node=None):
        self.key = key
        self.freq = freq
        self.data = data
        self.next_node = next_node

class LinkedList:
    def __init__(self, head=None, tail=None):
        self._head = head
        self._tail = tail
        self._size = 0

    def __iter__(self):
        current = self._head
        while current:
            yield current.key, current.freq
            current = current.next_node

    def __str__(self):
        return " ".join([str(item) for item in self])

    @property
    def head(self):
        return self._head

    @property
    def tail(self):
        return self._tail

    def list_insert_head(self, new_node):  # TODO error handling
        """
        Insert a new node (from an existing node or a key) at the head of the list.
        :param new_node: thing  to be inserted
        """
        if type(new_node) is not _Node:  # if the thing isn't already a node, make it a node
            new_node = _Node(new_node)
        new_node.next_node = self._head  # make item point to the current head of the list

        self._head = new_node  # make item be the new head of the list
        if self._size == 0:
            self._tail = self._head
        self._size += 1

    def list_insert_tail(self, new_node):  # add item (key or node) at tail of list, used in mergesort
        """
        Insert a new node at the tail of the list
        :param new_node:  thing to be inserted
        """
        n = self._tail
        if type(new_node) is not _Node:  # if the thing isn't already a node, make it a node
            self._tail = _Node(new_node)
        else:
            self._tail = new_node
        if self._size != 0:
            n.next_node = self.tail  # if this is not the only item
        else:
            self._head = self._tail  # if this is the only item, make it be the first item too
        self._size += 1
        return self.head, self.tail

    def list_insert_middle(self, prev, new_node):  # TODO error handling
        """
        Insert a new node, with key *key*, after the node *prev* in the list
        :param prev:  the _Node object to be inserted after
        :param key:  the key of the new node to be inserted
        """
        if type(new_node) is not _Node:
            new_node = _Node(new_node)  # make a node from key (if it is a key)
        new_node.next_node = prev.next_node  # make that node point at what the previous node is currently pointing at
        prev.next_node = new_node  # make the previous node point at the new node
        self._size += 1  # increase size by 1

    def list_delete(self, node):  # TODO error handling
        """
        Delete the specified node from the list, by changing the pointer on the node before to point at the next node.
        :param node: the _Node item you want to delete
        :return: the node you just removed
        """
        prev = self._head  # start at the head of the list
        if prev is not None:  # if there are some items in the list
            # while you haven't matched the node, and there are more nodes to look at
            while prev.next_node != node and prev.next_node is not None:
                prev = prev.next_node  # look at the next one
            if prev.next_node is not None:  # if the node you are looking at when you broke out of the loop has a next
                prev.next_node = node.next_node  # update pointer on prev to point at thing node was pointing at
        self._size -= 1
        return node

    def find_mid(self):  # used in mergesort, returns the middle node of a linked list
        x = self.head
        y = self.head
        while y is not None and y.next_node is not None:
            x = x.next_node
            y = y.next_node.next_node
        return x

    def pop(self):  # remove item at head of list, return it. used in mergesort
        # TODO error handling (empty list)
        n = self._head
        self._head = self._head.next_node
        self._size -= 1
        return n

    def swap_adjacent(self, prev=None):
        """
        Swap the two nodes immediately following the node specified. If prev is None, swap the first two nodes (since
        the head of a list has no previous node)    (so if you specify 7 in 789, you will get 798 with this method)
        :param prev: the node before the pair you want to switch
        :return:
        """
        # TODO error handling (eg when a, b are out of list)
        if prev is None:  # swap first and second items
            a = self.head
            b = self.head.next_node
            a.next_node = b.next_node
            self._head = b
            b.next_node = a
        else:
            a = prev.next_node
            b = prev.next_node.next_node
            a.next_node = b.next_node
            prev.next_node = b
            b.next_node = a
        if a.next_node is None:
            self._tail = a

    def swap(self, before_a, before_b):
        """
        Swap the nodes after the two nodes specified as arguments, by updating the pointers to them
        (If you specify 1 and 4 in 12345, you will get 15342)
        (If two nodes are adjacent, it will swap the two nodes after the first specified node. so 34 in 12345 will be 12354)
        :param before_a: node before the first node you want to swap
        :param before_b: node before the second node you want to swap
        :return: self
        """
        # TODO error handling as above - check a and b exist
        if before_a is None:
            a = self.head
        else:
            a = before_a.next_node
        if a == before_b:  # ie the nodes are adjacent
            self.swap_adjacent(before_a)
            return self

        if before_b is None:
            b = self.head
        else:
            b = before_b.next_node
        before_a.next_node = b
        before_b.next_node = a
        a.next_node, b.next_node = b.next_node, a.next_node
        return self

    def insertionsort(self):
        main = self.head.next_node  # this is the value from the main for loop on a list (start at second item)
        while main is not None:  # while there are still unchecked items in the list
            compare = self.head  # this is the thing from the inner loop on an array, start at the start of the list

            # this while loop will run from the start of the list until you either run out of nodes, or find one bigger than main
            while compare.next_node is not None and compare.next_node.key < main.key:  # there is a node next, and it is still smaller
                compare = compare.next_node  # look at the next one
            if compare.key > main.key:  # this catches the case where main is the smallest element in the list so far and
                                        # needs to be inserted at head of list. This is nasty, could do with being tidied
                move_node = self.list_delete(main)  # cut out main node
                self.list_insert_head(move_node)  # insert it at the head
                main = main.next_node
            else:  # all other cases (compare.key < main.key)
                temp = main
                main = main.next_node
                move_node = self.list_delete(temp)  # cut out the main node
                self.list_insert_middle(compare, move_node)  # insert it after the last node you found that was smaller
                                                               # main and not None

        # update the value of self.tail to be the biggest item!
        start = self.head
        while start.next_node is not None:
            start = start.next_node
        self._tail = start

    def binary_search(self, key):
        """
        Find the key using binary search
        :param key: the key to be found
        :return: node, if not found return None
        """
        self.insertionsort()
        max_i = self._size - 1  # max_i & min_i mark the "boundaries" of the search. now max_i is basically len(list)-1
        min_i = 0
        mid_i = (min_i + max_i)//2
        splitpoint = self.head
        for i in range(min_i, mid_i):  # loop over and find the first middle point (splitpoint)
            splitpoint = splitpoint.next_node  # will loop over and stop at mid_i

        while min_i < max_i and splitpoint.key != key and splitpoint.next_node is not None:
            if splitpoint.key < key:  # key is to the left of splitpoint (reachable with .next_node method)
                min_i = mid_i + 1  # move the left boundary to mid_i (focus on the right part)
                mid_i = (min_i + max_i)//2
                if min_i == max_i:  # when min_i == max_i for i in range won't work, have to change point manually
                # (although we have min_i< max_i in the while loop this is still possible as the loop will not break
                # immediately when min_i == max_i)
                    splitpoint = splitpoint.next_node  # if key is in list it will be this node
                    if splitpoint.key == key: # see if this is the key
                        return splitpoint
                    else:  # if splitpoint != key at this point, key is not in the list
                        return None

                else:  # normal cases, when min_i < max_i
                    for i in range(min_i, mid_i+1):  # will loop over and stop at the new mid_i
                        splitpoint = splitpoint.next_node
                continue  # go back to the start of while loop and see if the new splitpoint is at a reachable position to the key
            # this will break when 1.) when the key is found  2.) when min_i == max_i 3.) splitpoint.next_node is None

            else:  # key is to the right of the splitpoint (unreachable), splitpoint must be reset
                max_i = mid_i  # move the right boundary to mid_i (focus on the left part)
                mid_i = (min_i + max_i) // 2  # get a new mid_i
                splitpoint = self.head  # search for a new splitpoint from the head
                for i in range(0, mid_i):
                    splitpoint = splitpoint.next_node  # will loop over and stop at mid_i
                continue  # go back to the while loop and see if splitpoint < key

        if min_i != max_i:  # if the while loop breaks because splitpoint happens to be the key, it goes here
            return splitpoint
        else:   # if key is smaller than all items in the list, it will loop over the "else" part above and
            return None  # break when min_i == max_i and goes here (no key is found, None is returned)

    def mergesort(self):  # NOTE this sorts on the length of the data attribute
        # This is a method to make the list mergesort itself
        print(self.mergesort_recurse(self))

    def mergesort_recurse(self, lst):
        # this is the main recursive bit of mergesort
        if lst.head is None or lst.head.next_node is None:  # list of 0 or 1 things - trivially sorted
            return lst
        else:
            leftlist = LinkedList(lst.head)  # the left half of the list starts here
            # find the middle node
            mid = lst.find_mid()
            if mid.next_node is not None:
                rightlist = LinkedList(mid.next_node)
                mid.next_node = None  # divide the two parts
            else:
                rightlist = LinkedList(mid)
                leftlist.head.next_node = None

            left = self.mergesort_recurse(leftlist)
            right = self.mergesort_recurse(rightlist)
            lst = self.merge(left, right)
            self._head = lst.head
            return lst

    @staticmethod
    def merge(l, r):
        # this does the merging bit of mergesort
        merged = LinkedList()
        while l.head is not None or r.head is not None:  # there are items remaining in the left sublist
            if l.head is None:  # left sublist is empty
                merged.list_insert_tail(r.pop())  # remove the node at the head of r and push it to the new ll
            elif r.head is None:   # right sublist is empty
                merged.list_insert_tail(l.pop())  # remove the node at the head of l and push to new ll
            else:  # both sublists still have stuff in
                if l.head.key <= r.head.key:  # I fixed this line (it seems that errors come from this, but still not sorting)
                    # remove the node at the head of l and push to new ll
                    merged.list_insert_tail(l.pop())
                else:  # r.head < l.head
                    merged.list_insert_tail(r.pop())  # remove the node at the head of l and push to new ll
        return merged

    def quicksort(self):  # note this sorts in reverse order atm, and on the frequ
        print("quicksorting", self)
        return self.quicksort_recurse(self, self.head, self._tail)

    def quicksort_recurse(self, lst, start, end):
        if start and start.key != end.key:
            print("partitioning", start.key, end.key)
            print(self)
            pivot = self.partition(lst, start, end)
            self.quicksort_recurse(lst, start, pivot)
            self.quicksort_recurse(lst, pivot.next_node, end)

    @staticmethod
    def partition(lst, start, end):  # used in quicksort
        pivot = start
        i = pivot
        jprev = pivot  # track the node before j, used for swapping
        j = pivot.next_node
        while j != end.next_node:  # assuming unique keys
            if j.freq > pivot.freq:
                # swap  i and j
                if i.next_node.freq != j.freq:
                    lst.swap(i, jprev)
                i = i.next_node
            jprev = j
            j = j.next_node
        # swap pivot and j  # TODO swap properly!
        pivot.key, i.key = i.key, pivot.key
        pivot.freq, i.freq = i.freq, pivot.freq
        pivot.data, i.data = i.data, pivot.data
        print("pivot {}, i {}".format(pivot.key, i.key))
        return i

    def find(self, key):  # the trivial search algorithm, for testing ngram_list
        node = self.head
        while node:
            if node.key == key:
                return node
            else:
                node = node.next_node
        return None

# TODO error handling generally

if __name__ == "__main__":
    # test code goes here!
    ll = LinkedList()
    lk = LinkedList()
    for i in [5, 2, 9, 8, 1, 3, 6, 7, 14, 45, 15]:
        ll.list_insert_tail(i)
    print(ll)
    #lk.list_insert_tail(ll.pop())
    #print(lk)

    #ll.pop()
    #print(ll)
    ll.mergesort()
    print(ll, "what?")

    #ll.binary_search(7)
    #print(ll, "done")
    #ll.swap(ll.binary_search(1), ll.binary_search(4))
    #print(ll, "that's it")
    #print("head {}, tail {}".format(ll.head.key, ll.tail.key))

<|endoftext|>


<commit_before>#    Licensed under the Apache License, Version 2.0 (the "License"); you may
#    not use this file except in compliance with the License. You may obtain
#    a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#    License for the specific language governing permissions and limitations
#    under the License.
"""WSGI application initialization for Nova APIs."""

import os

from oslo_config import cfg
from oslo_log import log as logging
from paste import deploy

from nova import config
from nova import context
from nova import exception
from nova import objects
from nova import service
from nova import utils

CONF = cfg.CONF

CONFIG_FILES = ['api-paste.ini', 'nova.conf']

utils.monkey_patch()
objects.register_all()

def _get_config_files(env=None):
    if env is None:
        env = os.environ
    dirname = env.get('OS_NOVA_CONFIG_DIR', '/etc/nova').strip()
    return [os.path.join(dirname, config_file)
            for config_file in CONFIG_FILES]

def _setup_service(host, name):
    ctxt = context.get_admin_context()
    service_ref = objects.Service.get_by_host_and_binary(
        ctxt, host, name)
    if service_ref:
        service._update_service_ref(service_ref)
    else:
        try:
            service_obj = objects.Service(ctxt)
            service_obj.host = host
            service_obj.binary = 'nova-%s' % name
            service_obj.topic = None
            service_obj.report_count = 0
            service_obj.create()
        except (exception.ServiceTopicExists,
                exception.ServiceBinaryExists):
            # If we race to create a record with a sibling, don't
            # fail here.
            pass

def error_application(exc, name):
    # TODO(cdent): make this something other than a stub
    def application(environ, start_response):
        start_response('500 Internal Server Error', [
            ('Content-Type', 'text/plain; charset=UTF-8')])
        return ['Out of date %s service %s\n' % (name, exc)]
    return application

def init_application(name):
    conf_files = _get_config_files()
    config.parse_args([], default_config_files=conf_files)

    logging.setup(CONF, "nova")
    try:
        _setup_service(CONF.host, name)
    except exception.ServiceTooOld as exc:
        return error_application(exc, name)

    conf = conf_files[0]

    return deploy.loadapp('config:%s' % conf, name=name)
<commit_msg>Fix binary name<commit_after>#    Licensed under the Apache License, Version 2.0 (the "License"); you may
#    not use this file except in compliance with the License. You may obtain
#    a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#    License for the specific language governing permissions and limitations
#    under the License.
"""WSGI application initialization for Nova APIs."""

import os

from oslo_config import cfg
from oslo_log import log as logging
from paste import deploy

from nova import config
from nova import context
from nova import exception
from nova import objects
from nova import service
from nova import utils

CONF = cfg.CONF

CONFIG_FILES = ['api-paste.ini', 'nova.conf']

utils.monkey_patch()
objects.register_all()

def _get_config_files(env=None):
    if env is None:
        env = os.environ
    dirname = env.get('OS_NOVA_CONFIG_DIR', '/etc/nova').strip()
    return [os.path.join(dirname, config_file)
            for config_file in CONFIG_FILES]

def _setup_service(host, name):
    binary = name if name.startswith('nova-') else "nova-%s" % name

    ctxt = context.get_admin_context()
    service_ref = objects.Service.get_by_host_and_binary(
        ctxt, host, binary)
    if service_ref:
        service._update_service_ref(service_ref)
    else:
        try:
            service_obj = objects.Service(ctxt)
            service_obj.host = host
            service_obj.binary = binary
            service_obj.topic = None
            service_obj.report_count = 0
            service_obj.create()
        except (exception.ServiceTopicExists,
                exception.ServiceBinaryExists):
            # If we race to create a record with a sibling, don't
            # fail here.
            pass

def error_application(exc, name):
    # TODO(cdent): make this something other than a stub
    def application(environ, start_response):
        start_response('500 Internal Server Error', [
            ('Content-Type', 'text/plain; charset=UTF-8')])
        return ['Out of date %s service %s\n' % (name, exc)]
    return application

def init_application(name):
    conf_files = _get_config_files()
    config.parse_args([], default_config_files=conf_files)

    logging.setup(CONF, "nova")
    try:
        _setup_service(CONF.host, name)
    except exception.ServiceTooOld as exc:
        return error_application(exc, name)

    conf = conf_files[0]

    return deploy.loadapp('config:%s' % conf, name=name)
<|endoftext|>


<commit_before><commit_msg>Final update to the testcases after new dimensionalization<commit_after><|endoftext|>


<commit_before># vim: tabstop=4 shiftwidth=4 softtabstop=4

# Copyright 2010 United States Government as represented by the
# Administrator of the National Aeronautics and Space Administration.
# All Rights Reserved.
#
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
#    not use this file except in compliance with the License. You may obtain
#    a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#    License for the specific language governing permissions and limitations
#    under the License.

import os
import logging
import unittest

from nova import vendor
import IPy

from nova import flags
from nova import test
from nova import exception
from nova.compute.exception import NoMoreAddresses
from nova.compute import network
from nova.auth import users
from nova import utils

class NetworkTestCase(test.TrialTestCase):
    def setUp(self):
        super(NetworkTestCase, self).setUp()
        self.flags(fake_libvirt=True,
                   fake_storage=True,
                   fake_network=True,
                   network_size=32)
        logging.getLogger().setLevel(logging.DEBUG)
        self.manager = users.UserManager.instance()
        self.dnsmasq = FakeDNSMasq()
        try:
            self.manager.create_user('netuser', 'netuser', 'netuser')
        except: pass
        for i in range(0, 6):
            name = 'project%s' % i
            if not self.manager.get_project(name):
                self.manager.create_project(name, 'netuser', name)
        self.network = network.PublicNetworkController()

    def tearDown(self):
        super(NetworkTestCase, self).tearDown()
        for i in range(0, 6):
            name = 'project%s' % i
            self.manager.delete_project(name)
        self.manager.delete_user('netuser')

    def test_public_network_allocation(self):
        pubnet = IPy.IP(flags.FLAGS.public_range)
        address = self.network.allocate_ip("netuser", "project0", "public")
        self.assertTrue(IPy.IP(address) in pubnet)
        self.assertTrue(IPy.IP(address) in self.network.network)

    def test_allocate_deallocate_ip(self):
        address = network.allocate_ip(
                "netuser", "project0", utils.generate_mac())
        logging.debug("Was allocated %s" % (address))
        net = network.get_project_network("project0", "default")
        self.assertEqual(True, is_in_project(address, "project0"))
        mac = utils.generate_mac()
        hostname = "test-host"
        self.dnsmasq.issue_ip(mac, address, hostname, net.bridge_name)
        rv = network.deallocate_ip(address)

        # Doesn't go away until it's dhcp released
        self.assertEqual(True, is_in_project(address, "project0"))

        self.dnsmasq.release_ip(mac, address, hostname, net.bridge_name)
        self.assertEqual(False, is_in_project(address, "project0"))

    def test_range_allocation(self):
        mac = utils.generate_mac()
        secondmac = utils.generate_mac()
        hostname = "test-host"
        address = network.allocate_ip(
                    "netuser", "project0", mac)
        secondaddress = network.allocate_ip(
                "netuser", "project1", secondmac)
        net = network.get_project_network("project0", "default")
        secondnet = network.get_project_network("project1", "default")

        self.assertEqual(True, is_in_project(address, "project0"))
        self.assertEqual(True, is_in_project(secondaddress, "project1"))
        self.assertEqual(False, is_in_project(address, "project1"))

        # Addresses are allocated before they're issued
        self.dnsmasq.issue_ip(mac, address, hostname, net.bridge_name)
        self.dnsmasq.issue_ip(secondmac, secondaddress,
                                hostname, secondnet.bridge_name)

        rv = network.deallocate_ip(address)
        self.dnsmasq.release_ip(mac, address, hostname, net.bridge_name)
        self.assertEqual(False, is_in_project(address, "project0"))

        # First address release shouldn't affect the second
        self.assertEqual(True, is_in_project(secondaddress, "project1"))

        rv = network.deallocate_ip(secondaddress)
        self.dnsmasq.release_ip(secondmac, secondaddress,
                                hostname, secondnet.bridge_name)
        self.assertEqual(False, is_in_project(secondaddress, "project1"))

    def test_subnet_edge(self):
        secondaddress = network.allocate_ip("netuser", "project0",
                                utils.generate_mac())
        hostname = "toomany-hosts"
        for project in range(1,5):
            project_id = "project%s" % (project)
            mac = utils.generate_mac()
            mac2 = utils.generate_mac()
            mac3 = utils.generate_mac()
            address = network.allocate_ip(
                    "netuser", project_id, mac)
            address2 = network.allocate_ip(
                    "netuser", project_id, mac2)
            address3 = network.allocate_ip(
                    "netuser", project_id, mac3)
            self.assertEqual(False, is_in_project(address, "project0"))
            self.assertEqual(False, is_in_project(address2, "project0"))
            self.assertEqual(False, is_in_project(address3, "project0"))
            rv = network.deallocate_ip(address)
            rv = network.deallocate_ip(address2)
            rv = network.deallocate_ip(address3)
            net = network.get_project_network(project_id, "default")
            self.dnsmasq.release_ip(mac, address, hostname, net.bridge_name)
            self.dnsmasq.release_ip(mac2, address2, hostname, net.bridge_name)
            self.dnsmasq.release_ip(mac3, address3, hostname, net.bridge_name)
        net = network.get_project_network("project0", "default")
        rv = network.deallocate_ip(secondaddress)
        self.dnsmasq.release_ip(mac, address, hostname, net.bridge_name)

    def test_release_before_deallocate(self):
        pass

    def test_deallocate_before_issued(self):
        pass

    def test_too_many_addresses(self):
        """
        Network size is 32, there are 5 addresses reserved for VPN.
        So we should get 23 usable addresses
        """
        net = network.get_project_network("project0", "default")
        hostname = "toomany-hosts"
        macs = {}
        addresses = {}
        for i in range(0, 22):
            macs[i] = utils.generate_mac()
            addresses[i] = network.allocate_ip("netuser", "project0", macs[i])
            self.dnsmasq.issue_ip(macs[i], addresses[i], hostname, net.bridge_name)

        self.assertRaises(NoMoreAddresses, network.allocate_ip, "netuser", "project0", utils.generate_mac())

        for i in range(0, 22):
            rv = network.deallocate_ip(addresses[i])
            self.dnsmasq.release_ip(macs[i], addresses[i], hostname, net.bridge_name)

def is_in_project(address, project_id):
    return address in network.get_project_network(project_id).list_addresses()

def _get_project_addresses(project_id):
    project_addresses = []
    for addr in network.get_project_network(project_id).list_addresses():
        project_addresses.append(addr)
    return project_addresses

def binpath(script):
    return os.path.abspath(os.path.join(__file__, "../../../bin", script))

class FakeDNSMasq(object):
    def issue_ip(self, mac, ip, hostname, interface):
        cmd = "%s add %s %s %s" % (binpath('dhcpleasor.py'), mac, ip, hostname)
        env = {'DNSMASQ_INTERFACE': interface, 'TESTING' : '1'}
        (out, err) = utils.execute(cmd, addl_env=env)
        logging.debug("ISSUE_IP: %s, %s " % (out, err))

    def release_ip(self, mac, ip, hostname, interface):
        cmd = "%s del %s %s %s" % (binpath('dhcpleasor.py'), mac, ip, hostname)
        env = {'DNSMASQ_INTERFACE': interface, 'TESTING' : '1'}
        (out, err) = utils.execute(cmd, addl_env=env)
        logging.debug("RELEASE_IP: %s, %s " % (out, err))

<commit_msg>Adds a fix to the idempotency of the test_too_many_addresses test case by adding a simple property to the BaseNetwork class and calculating the number of available IPs by asking the network class to tell the test how many static and preallocated IP addresses are in use before entering the loop to "blow up" the address allocation...<commit_after># vim: tabstop=4 shiftwidth=4 softtabstop=4

# Copyright 2010 United States Government as represented by the
# Administrator of the National Aeronautics and Space Administration.
# All Rights Reserved.
#
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
#    not use this file except in compliance with the License. You may obtain
#    a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#    License for the specific language governing permissions and limitations
#    under the License.

import os
import logging
import unittest

from nova import vendor
import IPy

from nova import flags
from nova import test
from nova import exception
from nova.compute.exception import NoMoreAddresses
from nova.compute import network
from nova.auth import users
from nova import utils

class NetworkTestCase(test.TrialTestCase):
    def setUp(self):
        super(NetworkTestCase, self).setUp()
        self.flags(fake_libvirt=True,
                   fake_storage=True,
                   fake_network=True,
                   network_size=32)
        logging.getLogger().setLevel(logging.DEBUG)
        self.manager = users.UserManager.instance()
        self.dnsmasq = FakeDNSMasq()
        try:
            self.manager.create_user('netuser', 'netuser', 'netuser')
        except: pass
        for i in range(0, 6):
            name = 'project%s' % i
            if not self.manager.get_project(name):
                self.manager.create_project(name, 'netuser', name)
        self.network = network.PublicNetworkController()

    def tearDown(self):
        super(NetworkTestCase, self).tearDown()
        for i in range(0, 6):
            name = 'project%s' % i
            self.manager.delete_project(name)
        self.manager.delete_user('netuser')

    def test_public_network_allocation(self):
        pubnet = IPy.IP(flags.FLAGS.public_range)
        address = self.network.allocate_ip("netuser", "project0", "public")
        self.assertTrue(IPy.IP(address) in pubnet)
        self.assertTrue(IPy.IP(address) in self.network.network)

    def test_allocate_deallocate_ip(self):
        address = network.allocate_ip(
                "netuser", "project0", utils.generate_mac())
        logging.debug("Was allocated %s" % (address))
        net = network.get_project_network("project0", "default")
        self.assertEqual(True, is_in_project(address, "project0"))
        mac = utils.generate_mac()
        hostname = "test-host"
        self.dnsmasq.issue_ip(mac, address, hostname, net.bridge_name)
        rv = network.deallocate_ip(address)

        # Doesn't go away until it's dhcp released
        self.assertEqual(True, is_in_project(address, "project0"))

        self.dnsmasq.release_ip(mac, address, hostname, net.bridge_name)
        self.assertEqual(False, is_in_project(address, "project0"))

    def test_range_allocation(self):
        mac = utils.generate_mac()
        secondmac = utils.generate_mac()
        hostname = "test-host"
        address = network.allocate_ip(
                    "netuser", "project0", mac)
        secondaddress = network.allocate_ip(
                "netuser", "project1", secondmac)
        net = network.get_project_network("project0", "default")
        secondnet = network.get_project_network("project1", "default")

        self.assertEqual(True, is_in_project(address, "project0"))
        self.assertEqual(True, is_in_project(secondaddress, "project1"))
        self.assertEqual(False, is_in_project(address, "project1"))

        # Addresses are allocated before they're issued
        self.dnsmasq.issue_ip(mac, address, hostname, net.bridge_name)
        self.dnsmasq.issue_ip(secondmac, secondaddress,
                                hostname, secondnet.bridge_name)

        rv = network.deallocate_ip(address)
        self.dnsmasq.release_ip(mac, address, hostname, net.bridge_name)
        self.assertEqual(False, is_in_project(address, "project0"))

        # First address release shouldn't affect the second
        self.assertEqual(True, is_in_project(secondaddress, "project1"))

        rv = network.deallocate_ip(secondaddress)
        self.dnsmasq.release_ip(secondmac, secondaddress,
                                hostname, secondnet.bridge_name)
        self.assertEqual(False, is_in_project(secondaddress, "project1"))

    def test_subnet_edge(self):
        secondaddress = network.allocate_ip("netuser", "project0",
                                utils.generate_mac())
        hostname = "toomany-hosts"
        for project in range(1,5):
            project_id = "project%s" % (project)
            mac = utils.generate_mac()
            mac2 = utils.generate_mac()
            mac3 = utils.generate_mac()
            address = network.allocate_ip(
                    "netuser", project_id, mac)
            address2 = network.allocate_ip(
                    "netuser", project_id, mac2)
            address3 = network.allocate_ip(
                    "netuser", project_id, mac3)
            self.assertEqual(False, is_in_project(address, "project0"))
            self.assertEqual(False, is_in_project(address2, "project0"))
            self.assertEqual(False, is_in_project(address3, "project0"))
            rv = network.deallocate_ip(address)
            rv = network.deallocate_ip(address2)
            rv = network.deallocate_ip(address3)
            net = network.get_project_network(project_id, "default")
            self.dnsmasq.release_ip(mac, address, hostname, net.bridge_name)
            self.dnsmasq.release_ip(mac2, address2, hostname, net.bridge_name)
            self.dnsmasq.release_ip(mac3, address3, hostname, net.bridge_name)
        net = network.get_project_network("project0", "default")
        rv = network.deallocate_ip(secondaddress)
        self.dnsmasq.release_ip(mac, address, hostname, net.bridge_name)

    def test_release_before_deallocate(self):
        pass

    def test_deallocate_before_issued(self):
        pass

    def test_too_many_addresses(self):
        """
        Here, we test that a proper NoMoreAddresses exception is raised.

        However, the number of available IP addresses depends on the test
        environment's setup.

        Network size is 32.

            There are FLAGS.cnt_vpn_clients addresses reserved for VPN (NUM_RESERVED_VPN_IPS)

            And there are NUM_CONST_IPS that are always reserved by Nova for the necessary
            services (API, CloudPipe, etc)

        So we should get 32 - (NUM_STATIC_IPS +
                               NUM_PREALLOCATED_IPS +
                               NUM_RESERVED_VPN_IPS)
        usable addresses
        """
        net = network.get_project_network("project0", "default")

        # Determine expected number of available IP addresses
        num_static_ips = net.num_static_ips
        num_preallocated_ips = len(net.hosts.keys())
        num_reserved_vpn_ips = flags.FLAGS.cnt_vpn_clients
        num_available_ips = 32 - (num_static_ips + num_preallocated_ips + num_reserved_vpn_ips)

        hostname = "toomany-hosts"
        macs = {}
        addresses = {}
        for i in range(0, (num_available_ips - 1)):
            macs[i] = utils.generate_mac()
            addresses[i] = network.allocate_ip("netuser", "project0", macs[i])
            self.dnsmasq.issue_ip(macs[i], addresses[i], hostname, net.bridge_name)

        self.assertRaises(NoMoreAddresses, network.allocate_ip, "netuser", "project0", utils.generate_mac())

        for i in range(0, (num_available_ips - 1)):
            rv = network.deallocate_ip(addresses[i])
            self.dnsmasq.release_ip(macs[i], addresses[i], hostname, net.bridge_name)

def is_in_project(address, project_id):
    return address in network.get_project_network(project_id).list_addresses()

def _get_project_addresses(project_id):
    project_addresses = []
    for addr in network.get_project_network(project_id).list_addresses():
        project_addresses.append(addr)
    return project_addresses

def binpath(script):
    return os.path.abspath(os.path.join(__file__, "../../../bin", script))

class FakeDNSMasq(object):
    def issue_ip(self, mac, ip, hostname, interface):
        cmd = "%s add %s %s %s" % (binpath('dhcpleasor.py'), mac, ip, hostname)
        env = {'DNSMASQ_INTERFACE': interface, 'TESTING' : '1'}
        (out, err) = utils.execute(cmd, addl_env=env)
        logging.debug("ISSUE_IP: %s, %s " % (out, err))

    def release_ip(self, mac, ip, hostname, interface):
        cmd = "%s del %s %s %s" % (binpath('dhcpleasor.py'), mac, ip, hostname)
        env = {'DNSMASQ_INTERFACE': interface, 'TESTING' : '1'}
        (out, err) = utils.execute(cmd, addl_env=env)
        logging.debug("RELEASE_IP: %s, %s " % (out, err))

<|endoftext|>


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

import time
import pickle
import logging
import threading

import helpers.kronos as kronos

class Reader(threading.Thread):
    def __init__(self,
                 queue,                   # stores read messages
                 conf={},                 # additional configurations
                 writer=None,             # if writer is async, it must be provided
                 interval=None,           # interval of readings
                 checkpoint_enabled=False,# default is to not deal with checkpoint
                 checkpoint_interval=60   # interval between checkpoints
                 ):
        self.log = logging.getLogger()
        self.conf = conf
        self.processed = 0
        self.discarded = 0
        self.queue = queue
        self.writer = writer
        self.interval = interval
        self.checkpoint_enabled = checkpoint_enabled
        self.set_conf(conf)

        if self.checkpoint_enabled:
            self.last_checkpoint = ''
            if writer and \
                writer.last_checkpoint:
                self.last_checkpoint = writer.last_checkpoint
            if not hasattr(self, 'checkpoint_interval'):
                self.checkpoint_interval = checkpoint_interval
            if not hasattr(self, 'checkpoint_path'):
                self.log.error('Please, configure a checkpoint_path.')
                self.log.info('Aborting.')
                exit(-1)

        self.setup()

        self.scheduler = kronos.ThreadedScheduler()
        self.schedule_tasks()
        if self.checkpoint_enabled:
            self.schedule_checkpoint_writing()

        threading.Thread.__init__(self)

    def schedule_checkpoint_writing(self):
        self.scheduler.add_interval_task(self._write_checkpoint,
                                         "checkpoint writing",
                                         0,
                                         self.checkpoint_interval,
                                         kronos.method.threaded,
                                         [],
                                         None)

    def _read_checkpoint(self):
        """Read checkpoint file from disk."""
        try:
            if not os.path.exists(self.checkpoint_path):
                self.log.info('No checkpoint found in %s.' % self.checkpoint_path)
                return ''
            f = open(self.checkpoint_path, 'rb')
            read = pickle.load(f)
            f.close()
            if read:
                return read
            else:
                return ''
            self.log.info("Checkpoint read from %s" % self.checkpoint_path)
        except Exception, e:
            self.log.error('Error reading checkpoint in %s' % self.checkpoint_path)
            self.log.error(e)

    def _write_checkpoint(self):
        """Write checkpoint in disk."""
        try:
            lc = self.last_checkpoint
            f = open(self.checkpoint_path, 'w')
            pickle.dump(lc, f)
            f.close()
            self.log.info('Checkpoint written: %s' % lc)
        except Exception, e:
            self.log.error('Error writing checkpoint in %s' % self.checkpoint_path)
            self.log.error(e)

    def set_conf(self, conf):
        """Turns configuration properties
           into instance properties."""
        try:
            for item in conf:
                if isinstance(conf[item], str):
                    exec("self.%s = '%s'" % (item, conf[item]))
                else:
                    exec("self.%s = %s" % (item, conf[item]))
            self.log.info("Configuration settings added with success into reader.")
        except Exception, e:
            self.log.error("Invalid configuration item: %s" % item)
            self.log.error(e)

    def schedule_tasks(self):
        try:
            if self.interval:
                self.schedule_interval_task()
            else:
                self.schedule_single_task()
            self.log.info("Tasks scheduled with success")
        except Exception, e:
            self.log.error("Error while scheduling task")
            selg.log.error(e)

    def schedule_interval_task(self):
        self.scheduler.add_interval_task(self._process,
                                         "periodic task",
                                         0,
                                         self.interval,
                                         kronos.method.threaded,
                                         [],
                                         None)

    def schedule_single_task(self):
        self.scheduler.add_single_task(self._process,
                                       "single task",
                                       0,
                                       kronos.method.threaded,
                                       [],
                                       None)

    def _writer_callback(self):
        """Callback to writer for non periodic tasks.
           Shouldn't be called by subclasses."""
        try:
            self.log.debug("Calling writer_callback")
            self.writer.process()
        except Exception, e:
            self.log.error('Error when executing writer_callback')
            self.log.error(e)

    def _store(self, msg):
        """Internal method to store read messages.
           Shouldn't be called by subclasses."""
        try:
            if not self.queue.full():
                self.queue.put(msg)
                self.processed += 1
                self.log.debug("Stored message: %s" % msg)
            else:
                self.discarded += 1
                self.log.debug("Discarded message: %s, full queue" % msg)
        except Exception, e:
            self.log.error("Can't store in queue, message %s" % msg)
            print e

        if self.checkpoint_enabled:
            self._set_checkpoint(msg.checkpoint)

        if self.writer and not self.writer.interval:
            self._writer_callback()

    def _process(self):
        """Method called internally to process (read) a message.
           It is called in the end of each interval
           in the case of a periodic task.
           Shouldn't be called by subclasses"""
        if not self._read():
            self.log.info("Message can't be read")

    def _read(self):
        """Internal method that calls read() method.
           Shouldn't be called by subclasses."""
        try:
            return self.read()
        except Exception, e:
            self.log.error(e)

    def _set_checkpoint(self, checkpoint):
        """Wrapper method to set_checkpoint (user defined)
           to get exceptions"""
        try:
            self.last_checkpoint = checkpoint
            self.log.debug("Last checkpoint: %s" % checkpoint)
        except Exception, e:
            self.log.error('Error setting checkpoint')
            self.log.error(e)

    def store(self, msg):
        """Stores a read message.
           This should be called by subclasses."""
        self._store(msg)

    def setup(self):
        """Subclasses should implement."""
        pass

    def read(self):
        """Subclasses should implement."""
        pass

    def run(self):
        """Starts the reader"""
        self.scheduler.start()

    def __str__(self):
        return str(self.__dict__)
<commit_msg>fixing reader checkpoint storing<commit_after># -*- coding:utf-8 -*-

import time
import pickle
import logging
import threading

import helpers.kronos as kronos

class Reader(threading.Thread):
    def __init__(self,
                 queue,                   # stores read messages
                 conf={},                 # additional configurations
                 writer=None,             # if writer is async, it must be provided
                 interval=None,           # interval of readings
                 checkpoint_enabled=False,# default is to not deal with checkpoint
                 checkpoint_interval=60   # interval between checkpoints
                 ):
        self.log = logging.getLogger()
        self.conf = conf
        self.processed = 0
        self.discarded = 0
        self.queue = queue
        self.writer = writer
        self.interval = interval
        self.checkpoint_enabled = checkpoint_enabled
        self.set_conf(conf)

        if self.checkpoint_enabled:
            self.last_checkpoint = ''
            if writer and \
                writer.last_checkpoint:
                self.last_checkpoint = writer.last_checkpoint
            if not hasattr(self, 'checkpoint_interval'):
                self.checkpoint_interval = checkpoint_interval
            if not hasattr(self, 'checkpoint_path'):
                self.log.error('Please, configure a checkpoint_path.')
                self.log.info('Aborting.')
                exit(-1)

        self.setup()

        self.scheduler = kronos.ThreadedScheduler()
        self.schedule_tasks()
        if self.checkpoint_enabled:
            self.schedule_checkpoint_writing()

        threading.Thread.__init__(self)

    def schedule_checkpoint_writing(self):
        self.scheduler.add_interval_task(self._write_checkpoint,
                                         "checkpoint writing",
                                         0,
                                         self.checkpoint_interval,
                                         kronos.method.threaded,
                                         [],
                                         None)

    def _read_checkpoint(self):
        """Read checkpoint file from disk."""
        try:
            if not os.path.exists(self.checkpoint_path):
                self.log.info('No checkpoint found in %s.' % self.checkpoint_path)
                return ''
            f = open(self.checkpoint_path, 'rb')
            read = pickle.load(f)
            f.close()
            if read:
                return read
            else:
                return ''
            self.log.info("Checkpoint read from %s" % self.checkpoint_path)
        except Exception, e:
            self.log.error('Error reading checkpoint in %s' % self.checkpoint_path)
            self.log.error(e)

    def _write_checkpoint(self):
        """Write checkpoint in disk."""
        try:
            lc = self.last_checkpoint
            f = open(self.checkpoint_path, 'w')
            pickle.dump(lc, f)
            f.close()
            self.log.info('Checkpoint written: %s' % lc)
        except Exception, e:
            self.log.error('Error writing checkpoint in %s' % self.checkpoint_path)
            self.log.error(e)

    def set_conf(self, conf):
        """Turns configuration properties
           into instance properties."""
        try:
            for item in conf:
                if isinstance(conf[item], str):
                    exec("self.%s = '%s'" % (item, conf[item]))
                else:
                    exec("self.%s = %s" % (item, conf[item]))
            self.log.info("Configuration settings added with success into reader.")
        except Exception, e:
            self.log.error("Invalid configuration item: %s" % item)
            self.log.error(e)

    def schedule_tasks(self):
        try:
            if self.interval:
                self.schedule_interval_task()
            else:
                self.schedule_single_task()
            self.log.info("Tasks scheduled with success")
        except Exception, e:
            self.log.error("Error while scheduling task")
            selg.log.error(e)

    def schedule_interval_task(self):
        self.scheduler.add_interval_task(self._process,
                                         "periodic task",
                                         0,
                                         self.interval,
                                         kronos.method.threaded,
                                         [],
                                         None)

    def schedule_single_task(self):
        self.scheduler.add_single_task(self._process,
                                       "single task",
                                       0,
                                       kronos.method.threaded,
                                       [],
                                       None)

    def _writer_callback(self):
        """Callback to writer for non periodic tasks.
           Shouldn't be called by subclasses."""
        try:
            self.log.debug("Calling writer_callback")
            self.writer.process()
        except Exception, e:
            self.log.error('Error when executing writer_callback')
            self.log.error(e)

    def _store(self, msg):
        """Internal method to store read messages.
           Shouldn't be called by subclasses."""
        success = False
        try:
            if not self.queue.full():
                self.queue.put(msg)
                self.processed += 1
                self.log.debug("Stored message: %s" % msg)
                success = True
            else:
                self.discarded += 1
                self.log.debug("Discarded message: %s, full queue" % msg)
        except Exception, e:
            self.log.error("Can't store in queue, message %s" % msg)
            print e

        if success:
            if self.checkpoint_enabled:
                self._set_checkpoint(msg.checkpoint)

            if self.writer and not self.writer.interval:
                self._writer_callback()

    def _process(self):
        """Method called internally to process (read) a message.
           It is called in the end of each interval
           in the case of a periodic task.
           Shouldn't be called by subclasses"""
        if not self._read():
            self.log.info("Message can't be read")

    def _read(self):
        """Internal method that calls read() method.
           Shouldn't be called by subclasses."""
        try:
            return self.read()
        except Exception, e:
            self.log.error(e)

    def _set_checkpoint(self, checkpoint):
        """Wrapper method to set_checkpoint (user defined)
           to get exceptions"""
        try:
            self.last_checkpoint = checkpoint
            self.log.debug("Last checkpoint: %s" % checkpoint)
        except Exception, e:
            self.log.error('Error setting checkpoint')
            self.log.error(e)

    def store(self, msg):
        """Stores a read message.
           This should be called by subclasses."""
        self._store(msg)

    def setup(self):
        """Subclasses should implement."""
        pass

    def read(self):
        """Subclasses should implement."""
        pass

    def run(self):
        """Starts the reader"""
        self.scheduler.start()

    def __str__(self):
        return str(self.__dict__)
<|endoftext|>


<commit_before>__all__ = ('version', '__version__')

version = (0, 15, 0, 1)
__version__ = '.'.join(str(x) for x in version)
<commit_msg>version 0.15.1<commit_after>__all__ = ('version', '__version__')

version = (0, 15, 1)
__version__ = '.'.join(str(x) for x in version)
<|endoftext|>


<commit_before>from linop import BaseLinearOperator, LinearOperator
from linop import ShapeError, null_log
import numpy as np
import itertools

class BlockLinearOperator(LinearOperator):

    """
    A linear operator defined by blocks. Each block must be a linear operator.

    `blocks` should be a list of lists describing the blocks row-wise.
    If there is only one block row, it should be specified as
    `[[b1, b2, ..., bn]]`, not as `[b1, b2, ..., bn]`.

    If the overall linear operator is symmetric, only its upper triangle
    need be specified, e.g., `[[A,B,C], [D,E], [F]]`, and the blocks on the
    diagonal must be square and symmetric.

    """

    def __init__(self, blocks, symmetric=False, **kwargs):
        # If building a symmetric operator, fill in the blanks.
        # They're just references to existing objects.
        if symmetric:
            nrow = len(blocks)
            ncol = len(blocks[0])
            if nrow != ncol:
                raise ShapeError('Inconsistent shape.')

            for block_row in blocks:
                if not block_row[0].symmetric:
                    raise ValueError('Blocks on diagonal must be symmetric.')

            self._blocks = blocks[:]
            for i in range(1, nrow):
                for j in range(i - 1, -1, -1):
                    self._blocks[i].insert(0, self._blocks[j][i].T)

        else:
            self._blocks = blocks

        log = kwargs.get('logger', null_log)
        log.debug('Building new BlockLinearOperator')

        nargins = [[blk.shape[-1] for blk in row] for row in self._blocks]
        log.debug('nargins = ' + repr(nargins))
        nargins_by_row = [nargin[0] for nargin in nargins]
        if min(nargins_by_row) != max(nargins_by_row):
            raise ShapeError('Inconsistent block shapes')

        nargouts = [[blk.shape[0] for blk in row] for row in self._blocks]
        log.debug('nargouts = ' + repr(nargouts))
        for row in nargouts:
            if min(row) != max(row):
                raise ShapeError('Inconsistent block shapes')

        nargin = sum(nargins[0])
        nargout = sum([out[0] for out in nargouts])

        # Create blocks of transpose operator.
        blocksT = map(lambda *row: [blk.T for blk in row], *self._blocks)

        def blk_matvec(x, blks):
            nargins = [[blk.shape[-1] for blk in blkrow] for blkrow in blks]
            nargouts = [[blk.shape[0] for blk in blkrow] for blkrow in blks]
            nargin = sum(nargins[0])
            nargout = sum([out[0] for out in nargouts])
            nx = len(x)
            self.logger.debug('Multiplying with a vector of size %d' % nx)
            self.logger.debug('nargin=%d, nargout=%d' % (nargin, nargout))
            if nx != nargin:
                raise ShapeError('Multiplying with vector of wrong shape.')

            result_type = np.result_type(self.dtype, x.dtype)
            y = np.zeros(nargout, dtype=result_type)

            nblk_row = len(blks)
            nblk_col = len(blks[0])

            row_start = col_start = 0
            for row in range(nblk_row):
                row_end = row_start + nargouts[row][0]
                yout = y[row_start:row_end]
                for col in range(nblk_col):
                    col_end = col_start + nargins[0][col]
                    xin = x[col_start:col_end]
                    B = blks[row][col]
                    yout[:] += B * xin
                    col_start = col_end
                row_start = row_end
                col_start = 0

            return y

        flat_blocks = list(itertools.chain(*blocks))
        blk_dtypes = [blk.dtype for blk in flat_blocks]
        op_dtype = np.result_type(*blk_dtypes)

        super(BlockLinearOperator, self).__init__(
            nargin, nargout,
            symmetric=symmetric,
            matvec=lambda x: blk_matvec(x, self._blocks),
            matvec_transp=lambda x: blk_matvec(x, blocksT),
            dtype=op_dtype)

        self.H._blocks = blocksT

    @property
    def blocks(self):
        """The list of blocks defining the block operator."""
        return self._blocks

    def __getitem__(self, indices):
        blks = np.matrix(self._blocks, dtype=object)[indices]
        # If indexing narrowed it down to a single block, return it.
        if isinstance(blks, BaseLinearOperator):
            return blks
        # Otherwise, we have a matrix of blocks.
        return BlockLinearOperator(blks.tolist(), symmetric=False)

    def __contains__(self, op):
        return op in self._blocks

    def __iter__(self):
        for block in self._blocks:
            yield block

class BlockDiagonalLinearOperator(LinearOperator):

    """
    A block diagonal linear operator.

    Each block must be a linear operator.
    The blocks may be specified as one list, e.g., `[A, B, C]`.

    """

    def __init__(self, blocks, **kwargs):

        symmetric = reduce(lambda x, y: x and y,
                           [blk.symmetric for blk in blocks])

        self._blocks = blocks

        log = kwargs.get('logger', null_log)
        log.debug('Building new BlockDiagonalLinearOperator')

        nargins = [blk.shape[-1] for blk in blocks]
        log.debug('nargins = ' + repr(nargins))

        nargouts = [blk.shape[0] for blk in blocks]
        log.debug('nargouts = ' + repr(nargouts))

        nargin = sum(nargins)
        nargout = sum(nargouts)

        # Create blocks of transpose operator.
        blocksT = [blk.T for blk in blocks]

        def blk_matvec(x, blks):
            nx = len(x)
            nargins = [blk.shape[-1] for blk in blocks]
            nargin = sum(nargins)
            nargouts = [blk.shape[0] for blk in blocks]
            nargout = sum(nargouts)
            self.logger.debug('Multiplying with a vector of size %d' % nx)
            self.logger.debug('nargin=%d, nargout=%d' % (nargin, nargout))
            if nx != nargin:
                raise ShapeError('Multiplying with vector of wrong shape.')

            result_type = np.result_type(self.dtype, x.dtype)
            y = np.empty(nargout, dtype=result_type)

            nblks = len(blks)

            row_start = col_start = 0
            for blk in range(nblks):
                row_end = row_start + nargouts[blk]
                yout = y[row_start:row_end]

                col_end = col_start + nargins[blk]
                xin = x[col_start:col_end]

                B = blks[blk]
                yout[:] = B * xin

                col_start = col_end
                row_start = row_end

            return y

        blk_dtypes = [blk.dtype for blk in blocks]
        op_dtype = np.result_type(*blk_dtypes)

        super(BlockDiagonalLinearOperator, self).__init__(
            nargin, nargout,
            symmetric=symmetric,
            matvec=lambda x: blk_matvec(x, self._blocks),
            matvec_transp=lambda x: blk_matvec(x, blocksT),
            dtype=op_dtype)

        self.H._blocks = blocksT

    @property
    def blocks(self):
        """The list of blocks defining the block diagonal operator."""
        return self._blocks

    def __getitem__(self, idx):
        blks = self._blocks[idx]
        if isinstance(idx, slice):
            return BlockDiagonalLinearOperator(blks, symmetric=self.symmetric)
        return blks

    def __setitem__(self, idx, ops):
        if not isinstance(ops, BaseLinearOperator):
            if isinstance(ops, list) or isinstance(ops, tuple):
                for op in ops:
                    if not isinstance(op, BaseLinearOperator):
                        msg = 'Block operators can only contain'
                        msg += ' linear operators'
                        raise ValueError(msg)
        self._blocks[idx] = ops

class BlockPreconditioner(BlockLinearOperator):

    """An alias for ``BlockLinearOperator``.

    Holds an additional ``solve`` method equivalent to ``__mul__``.

    """

    def solve(self, x):
        """An alias to __call__."""
        return self.__call__(x)

class BlockDiagonalPreconditioner(BlockDiagonalLinearOperator):

    """
    An alias for ``BlockDiagonalLinearOperator``.

    Holds an additional ``solve`` method equivalent to ``__mul__``.

    """

    def solve(self, x):
        """An alias to __call__."""
        return self.__call__(x)
<commit_msg>fix #12: provide vertical and horizontal blockop<commit_after>from linop import BaseLinearOperator, LinearOperator
from linop import ShapeError, null_log
import numpy as np
import itertools

class BlockLinearOperator(LinearOperator):

    """
    A linear operator defined by blocks. Each block must be a linear operator.

    `blocks` should be a list of lists describing the blocks row-wise.
    If there is only one block row, it should be specified as
    `[[b1, b2, ..., bn]]`, not as `[b1, b2, ..., bn]`.

    If the overall linear operator is symmetric, only its upper triangle
    need be specified, e.g., `[[A,B,C], [D,E], [F]]`, and the blocks on the
    diagonal must be square and symmetric.

    """

    def __init__(self, blocks, symmetric=False, **kwargs):
        # If building a symmetric operator, fill in the blanks.
        # They're just references to existing objects.
        if symmetric:
            nrow = len(blocks)
            ncol = len(blocks[0])
            if nrow != ncol:
                raise ShapeError('Inconsistent shape.')

            for block_row in blocks:
                if not block_row[0].symmetric:
                    raise ValueError('Blocks on diagonal must be symmetric.')

            self._blocks = blocks[:]
            for i in range(1, nrow):
                for j in range(i - 1, -1, -1):
                    self._blocks[i].insert(0, self._blocks[j][i].T)

        else:
            self._blocks = blocks

        log = kwargs.get('logger', null_log)
        log.debug('Building new BlockLinearOperator')

        nargins = [[blk.shape[-1] for blk in row] for row in self._blocks]
        log.debug('nargins = ' + repr(nargins))
        nargins_by_row = [nargin[0] for nargin in nargins]
        if min(nargins_by_row) != max(nargins_by_row):
            raise ShapeError('Inconsistent block shapes')

        nargouts = [[blk.shape[0] for blk in row] for row in self._blocks]
        log.debug('nargouts = ' + repr(nargouts))
        for row in nargouts:
            if min(row) != max(row):
                raise ShapeError('Inconsistent block shapes')

        nargin = sum(nargins[0])
        nargout = sum([out[0] for out in nargouts])

        # Create blocks of transpose operator.
        blocksT = map(lambda *row: [blk.T for blk in row], *self._blocks)

        def blk_matvec(x, blks):
            nargins = [[blk.shape[-1] for blk in blkrow] for blkrow in blks]
            nargouts = [[blk.shape[0] for blk in blkrow] for blkrow in blks]
            nargin = sum(nargins[0])
            nargout = sum([out[0] for out in nargouts])
            nx = len(x)
            self.logger.debug('Multiplying with a vector of size %d' % nx)
            self.logger.debug('nargin=%d, nargout=%d' % (nargin, nargout))
            if nx != nargin:
                raise ShapeError('Multiplying with vector of wrong shape.')

            result_type = np.result_type(self.dtype, x.dtype)
            y = np.zeros(nargout, dtype=result_type)

            nblk_row = len(blks)
            nblk_col = len(blks[0])

            row_start = col_start = 0
            for row in range(nblk_row):
                row_end = row_start + nargouts[row][0]
                yout = y[row_start:row_end]
                for col in range(nblk_col):
                    col_end = col_start + nargins[0][col]
                    xin = x[col_start:col_end]
                    B = blks[row][col]
                    yout[:] += B * xin
                    col_start = col_end
                row_start = row_end
                col_start = 0

            return y

        flat_blocks = list(itertools.chain(*blocks))
        blk_dtypes = [blk.dtype for blk in flat_blocks]
        op_dtype = np.result_type(*blk_dtypes)

        super(BlockLinearOperator, self).__init__(
            nargin, nargout,
            symmetric=symmetric,
            matvec=lambda x: blk_matvec(x, self._blocks),
            matvec_transp=lambda x: blk_matvec(x, blocksT),
            dtype=op_dtype)

        self.H._blocks = blocksT

    @property
    def blocks(self):
        """The list of blocks defining the block operator."""
        return self._blocks

    def __getitem__(self, indices):
        blks = np.matrix(self._blocks, dtype=object)[indices]
        # If indexing narrowed it down to a single block, return it.
        if isinstance(blks, BaseLinearOperator):
            return blks
        # Otherwise, we have a matrix of blocks.
        return BlockLinearOperator(blks.tolist(), symmetric=False)

    def __contains__(self, op):
        return op in self._blocks

    def __iter__(self):
        for block in self._blocks:
            yield block

class BlockDiagonalLinearOperator(LinearOperator):

    """
    A block diagonal linear operator.

    Each block must be a linear operator.
    The blocks may be specified as one list, e.g., `[A, B, C]`.

    """

    def __init__(self, blocks, **kwargs):

        symmetric = reduce(lambda x, y: x and y,
                           [blk.symmetric for blk in blocks])

        self._blocks = blocks

        log = kwargs.get('logger', null_log)
        log.debug('Building new BlockDiagonalLinearOperator')

        nargins = [blk.shape[-1] for blk in blocks]
        log.debug('nargins = ' + repr(nargins))

        nargouts = [blk.shape[0] for blk in blocks]
        log.debug('nargouts = ' + repr(nargouts))

        nargin = sum(nargins)
        nargout = sum(nargouts)

        # Create blocks of transpose operator.
        blocksT = [blk.T for blk in blocks]

        def blk_matvec(x, blks):
            nx = len(x)
            nargins = [blk.shape[-1] for blk in blocks]
            nargin = sum(nargins)
            nargouts = [blk.shape[0] for blk in blocks]
            nargout = sum(nargouts)
            self.logger.debug('Multiplying with a vector of size %d' % nx)
            self.logger.debug('nargin=%d, nargout=%d' % (nargin, nargout))
            if nx != nargin:
                raise ShapeError('Multiplying with vector of wrong shape.')

            result_type = np.result_type(self.dtype, x.dtype)
            y = np.empty(nargout, dtype=result_type)

            nblks = len(blks)

            row_start = col_start = 0
            for blk in range(nblks):
                row_end = row_start + nargouts[blk]
                yout = y[row_start:row_end]

                col_end = col_start + nargins[blk]
                xin = x[col_start:col_end]

                B = blks[blk]
                yout[:] = B * xin

                col_start = col_end
                row_start = row_end

            return y

        blk_dtypes = [blk.dtype for blk in blocks]
        op_dtype = np.result_type(*blk_dtypes)

        super(BlockDiagonalLinearOperator, self).__init__(
            nargin, nargout,
            symmetric=symmetric,
            matvec=lambda x: blk_matvec(x, self._blocks),
            matvec_transp=lambda x: blk_matvec(x, blocksT),
            dtype=op_dtype)

        self.H._blocks = blocksT

    @property
    def blocks(self):
        """The list of blocks defining the block diagonal operator."""
        return self._blocks

    def __getitem__(self, idx):
        blks = self._blocks[idx]
        if isinstance(idx, slice):
            return BlockDiagonalLinearOperator(blks, symmetric=self.symmetric)
        return blks

    def __setitem__(self, idx, ops):
        if not isinstance(ops, BaseLinearOperator):
            if isinstance(ops, list) or isinstance(ops, tuple):
                for op in ops:
                    if not isinstance(op, BaseLinearOperator):
                        msg = 'Block operators can only contain'
                        msg += ' linear operators'
                        raise ValueError(msg)
        self._blocks[idx] = ops

class BlockPreconditioner(BlockLinearOperator):

    """An alias for ``BlockLinearOperator``.

    Holds an additional ``solve`` method equivalent to ``__mul__``.

    """

    def solve(self, x):
        """An alias to __call__."""
        return self.__call__(x)

class BlockDiagonalPreconditioner(BlockDiagonalLinearOperator):

    """
    An alias for ``BlockDiagonalLinearOperator``.

    Holds an additional ``solve`` method equivalent to ``__mul__``.

    """

    def solve(self, x):
        """An alias to __call__."""
        return self.__call__(x)

class BlockHorizontalLinearOperator(BlockLinearOperator):

    """
    A block horizontal linear operator.

    Each block must be a linear operator.
    The blocks must be specified as one list, e.g., `[A, B, C]`.

    """

    def __init__(self, blocks, **kwargs):

        super(BlockHorizontalLinearOperator, self).__init__(
            blocks=[[blk for blk in blocks]])

class BlockVerticalLinearOperator(BlockLinearOperator):

    """
    A block vertical linear operator.

    Each block must be a linear operator.
    The blocks must be specified as one list, e.g., `[A, B, C]`.

    """

    def __init__(self, blocks, **kwargs):

        super(BlockVerticalLinearOperator, self).__init__(
            blocks=[[blk] for blk in blocks])
<|endoftext|>


<commit_before>from django.conf.urls import patterns, include, url

# Uncomment the next two lines to enable the admin:
from django.contrib import admin
from plstackapi.planetstack.views.roles import RoleListCreate
from plstackapi.planetstack.views.api_root import api_root
from plstackapi.planetstack.models import Site
from rest_framework import generics

admin.autodiscover()

urlpatterns = patterns('',
    # Examples:
    # url(r'^$', 'planetstack.views.home', name='home'),
    # url(r'^planetstack/', include('planetstack.foo.urls')),

    # Uncomment the admin/doc line below to enable admin documentation:
    # url(r'^admin/doc/', include('django.contrib.admindocs.urls')),

    # Uncomment the next line to enable the admin:
    url(r'^admin/', include(admin.site.urls)),

    url(r'^plstackapi/$', api_root),

    url(r'^plstackapi/roles/$', views.RoleListCreate.as_view(), name='role-list'),

    #url(r'^plstackapi/sites/$', views.SiteList.as_view(), name='site-list'),
    #url(r'^plstackapi/sites/(?P<pk>[0-9]+)/$', views.SiteDetail.as_view(), name='site-detail'),

    #url(r'^plstackapi/slices/$', views.SliceList.as_view(), name='slice-list'),
    #url(r'^plstackapi/slices/(?P<pk>[0-9]+)/$', views.SliceDetail.as_view(), name='slice-detail'),

    #url(r'^plstackapi/slivers/$', views.SliverList.as_view()),
    #url(r'^plstackapi/slivers/(?P<pk>[0-9]+)/$', views.SliverDetail.as_view()),

    #url(r'^plstackapi/nodes/$', views.NodeList.as_view(), name='node-list'),
    #url(r'^plstackapi/nodes/(?P<pk>[0-9]+)/$', views.NodeDetail.as_view(), name='node-detail'),

    #url(r'^plstackapi/deploymentnetworks/$', views.DeploymentNetworkList.as_view(), name='deploymentnetwork-list'),
    #url(r'^plstackapi/deploymentnetworks/(?P<pk>[0-9]+)/$', views.DeploymentNetworkDetail.as_view(), name='deploymentnetwork-detail'),

    #url(r'^plstackapi/sitedeploymentnetworks/$', views.SiteDeploymentNetworkList.as_view(), name='sitedeploymentnetwork-list'),
    #url(r'^plstackapi/sitedeploymentnetworks/(?P<pk>[0-9]+)/$', views.SiteDeploymentNetworkDetail.as_view(), name='sitedeploymentnetwork-detail'),

    #Adding in rest_framework urls
    url(r'^plstackapi/', include('rest_framework.urls', namespace='rest_framework')),

)
<commit_msg>fix NameError<commit_after>from django.conf.urls import patterns, include, url

# Uncomment the next two lines to enable the admin:
from django.contrib import admin
from plstackapi.planetstack.views.roles import RoleListCreate
from plstackapi.planetstack.views.api_root import api_root
from plstackapi.planetstack.models import Site
from rest_framework import generics

admin.autodiscover()

urlpatterns = patterns('',
    # Examples:
    # url(r'^$', 'planetstack.views.home', name='home'),
    # url(r'^planetstack/', include('planetstack.foo.urls')),

    # Uncomment the admin/doc line below to enable admin documentation:
    # url(r'^admin/doc/', include('django.contrib.admindocs.urls')),

    # Uncomment the next line to enable the admin:
    url(r'^admin/', include(admin.site.urls)),

    url(r'^plstackapi/$', api_root),

    url(r'^plstackapi/roles/$', RoleListCreate.as_view(), name='role-list'),

    #url(r'^plstackapi/sites/$', views.SiteList.as_view(), name='site-list'),
    #url(r'^plstackapi/sites/(?P<pk>[0-9]+)/$', views.SiteDetail.as_view(), name='site-detail'),

    #url(r'^plstackapi/slices/$', views.SliceList.as_view(), name='slice-list'),
    #url(r'^plstackapi/slices/(?P<pk>[0-9]+)/$', views.SliceDetail.as_view(), name='slice-detail'),

    #url(r'^plstackapi/slivers/$', views.SliverList.as_view()),
    #url(r'^plstackapi/slivers/(?P<pk>[0-9]+)/$', views.SliverDetail.as_view()),

    #url(r'^plstackapi/nodes/$', views.NodeList.as_view(), name='node-list'),
    #url(r'^plstackapi/nodes/(?P<pk>[0-9]+)/$', views.NodeDetail.as_view(), name='node-detail'),

    #url(r'^plstackapi/deploymentnetworks/$', views.DeploymentNetworkList.as_view(), name='deploymentnetwork-list'),
    #url(r'^plstackapi/deploymentnetworks/(?P<pk>[0-9]+)/$', views.DeploymentNetworkDetail.as_view(), name='deploymentnetwork-detail'),

    #url(r'^plstackapi/sitedeploymentnetworks/$', views.SiteDeploymentNetworkList.as_view(), name='sitedeploymentnetwork-list'),
    #url(r'^plstackapi/sitedeploymentnetworks/(?P<pk>[0-9]+)/$', views.SiteDeploymentNetworkDetail.as_view(), name='sitedeploymentnetwork-detail'),

    #Adding in rest_framework urls
    url(r'^plstackapi/', include('rest_framework.urls', namespace='rest_framework')),

)
<|endoftext|>