bebraw
1/5/2010 - 7:59 PM

file.py

from mock import Mock
from placidity.plugin_loader import PluginLoader

class TestPluginLoader:

    def test_load_plugins(self):
        class Plugin1: pass
        class Plugin2: pass

        plugin_dir = Mock()
        plugin1_dir = self.create_plugin_dir('plugin1', Plugin1)
        plugin2_dir = self.create_plugin_dir('plugin2', Plugin2)
        plugin_dir.children = (plugin1_dir, plugin2_dir)

        plugin_loader = PluginLoader()

        assert plugin_loader.load(plugin_dir) == [Plugin1, Plugin2]

    def create_plugin_dir(self, name, plugin_class):
        plugin_dir = Mock()
        plugin_dir.name = name
        plugin_dir.children = Mock()

        plugin_file = self.create_plugin_file(name, plugin_class)
        plugin_dir.find.return_value = plugin_file

        return plugin_dir

    def create_plugin_file(self, name, klass):
        plugin_file = Mock()
        plugin_file.classes = {name: klass, }

        return plugin_file
# -*- coding: utf-8 -*-
from placidity.node import Node, TreeNode


class TestNode():

    def test_append_children_to_node(self):
        node1, node2 = Node(), Node()

        node1.children.append(node2)

        assert node1.children[0] == node2
        assert node2.parents[0] == node1

    def test_append_parents_to_node(self):
        node1, node2 = Node(), Node()

        node1.parents.append(node2)

        assert node1.parents[0] == node2
        assert node2.children[0] == node1

    def test_append_same_node_as_child_and_parent(self):
        node1, node2 = Node(), Node()

        node1.children.append(node2)
        node1.parents.append(node2)

        assert node1.children[0] == node2
        assert node1.parents[0] == node2

        assert node2.children[0] == node1
        assert node2.parents[0] == node1

    def test_append_same_node_as_child_multiple_times(self):
        node1, node2 = Node(), Node()

        node1.children.append(node2)
        node1.children.append(node2)
        node1.children.append(node2)

        assert node1.children[0] == node2
        assert node2.parents[0] == node1

        assert len(node1.children) == 1
        assert len(node2.parents) == 1

    def test_append_same_node_as_parent_multiple_times(self):
        node1, node2 = Node(), Node()

        node1.parents.append(node2)
        node1.parents.append(node2)
        node1.parents.append(node2)

        assert node1.parents[0] == node2
        assert node2.children[0] == node1

        assert len(node1.parents) == 1
        assert len(node2.children) == 1

    def test_multi_append(self):
        node1, node2, node3 = Node(), Node(), Node()

        node1.children.append(node2, node3)

        assert len(node1.children) == 2
        assert node2 in node1.children
        assert node3 in node1.children

    def test_remove_child_node(self):
        node1, node2 = Node(), Node()

        node1.children.append(node2)
        node1.children.remove(node2)

        assert len(node1.children) == 0
        assert len(node2.parents) == 0

    def test_remove_parent_node(self):
        node1, node2 = Node(), Node()

        node1.parents.append(node2)
        node1.parents.remove(node2)

        assert len(node1.parents) == 0
        assert len(node2.children) == 0

    def test_remove_same_node_multiple_times(self):
        node1, node2 = Node(), Node()

        node1.parents.append(node2)
        node1.parents.remove(node2)
        node1.parents.remove(node2)
        node1.parents.remove(node2)

        assert len(node1.parents) == 0
        assert len(node2.children) == 0

    def test_multi_remove(self):
        node1, node2, node3 = Node(), Node(), Node()

        node1.children.append(node2, node3)
        node1.children.remove(node2, node3)

        assert len(node1.children) == 0

    def test_find_immediate_child_node(self):
        node1, node2 = Node(), Node()
        node2.name = 'node to be found'

        node1.children.append(node2)

        assert node1.find_child(name='node to be found') == node2

    def test_find_child_node_no_results(self):
        node1 = Node()

        assert node1.find_child(name='just some name') == None

    def test_find_child_node_from_node_tree(self):
        node1 = Node()
        node1a = Node()
        node1a1 = Node()
        node1a1.color = 'blue'
        node1a2 = Node()
        node1a2.value = 13
        node1b = Node()
        node1b1 = Node()
        node1b1.find_me = True
        node1b1.color = 'blue'

        node1.children.append(node1a, node1b)
        node1a.children.append(node1a1, node1a2)
        node1b.children.append(node1b1)

        assert node1.find_child(value=13) == node1a2
        assert node1.find_child(find_me=True) == node1b1
        assert node1.find_child(color='blue') == [node1a1, node1b1]

    def test_find_immediate_parent_node(self):
        node1, node2 = Node(), Node()
        node2.name = 'node to be found'

        node1.parents.append(node2)

        assert node1.find_parent(name='node to be found') == node2

    def test_find_parent_node_no_results(self):
        node1 = Node()

        assert node1.find_parent(name='just some name') == None

    def test_find_parent_node_from_node_tree(self):
        node1 = Node()
        node1a = Node()
        node1a1 = Node()
        node1a1.color = 'blue'
        node1a2 = Node()
        node1a2.value = 13
        node1b = Node()
        node1b1 = Node()
        node1b1.find_me = True
        node1b1.color = 'blue'

        node1.parents.append(node1a, node1b)
        node1a.parents.append(node1a1, node1a2)

        node1b.parents.append(node1b1)

        assert node1.find_parent(value=13) == node1a2
        assert node1.find_parent(find_me=True) == node1b1
        assert node1.find_parent(color='blue') == [node1a1, node1b1]
        assert node1.find_parent(find_me=True, color='blue') == node1b1

    def test_find_root(self):
        node1, node1a, node1b, node1a1 = Node(), Node(), Node(), Node()

        node1.children.append(node1a, node1b)
        node1a.children.append(node1a1)

        assert node1.find_root() == None
        assert node1a.find_root() == node1
        assert node1b.find_root() == node1
        assert node1a1.find_root() == node1

    def test_cyclic_find(self):
        node1, node2 = Node(), Node()

        node1.children.append(node2)
        node2.children.append(node1)

        assert node1.find_root() == None
        assert node2.find_root() == None

    def test_find_parent_with_value_name(self):
        node1, node2, node3 = Node(), Node(), Node()
        node3.attribute_to_find = 'find me'

        node1.parents.append(node2)
        node2.parents.append(node3)

        assert node1.find_parent_with_attribute('attribute_to_find') == node3

    def test_walk(self):
        node1, node2, node3, node4 = Node(), Node(), Node(), Node()
        node5 = Node()

        node1.children.append(node2)
        node1.children.append(node5)

        node2.children.append(node3)
        node2.children.append(node4)

        result = (node1, node3, node4, node2, node5 )

        for i, node in enumerate(node1.walk()):
            assert node == result[i], '%s %s %s' % (i, node, result[i])


class TestTreeNode():

    def test_set_parent(self):
        node1, node2 = TreeNode(), TreeNode()

        node1.parent = node2
        assert node1.parent == node2
        assert node2.children == [node1, ]

    def test_set_parent_twice(self):
        node1, node2, node3 = TreeNode(), TreeNode(), TreeNode()

        node1.parent = node2
        node1.parent = node3
        assert node2.children == []
        assert node3.children == [node1, ]

    def test_find(self):
        node1, node2, node3 = TreeNode(), TreeNode(), TreeNode()

        node2.parent = node1
        node3.parent = node1
        node2.name = 'foo'
        node3.name = 'bar'

        assert node1.find(name='foo') == node2
        assert node1.find(name='bar') == node3
        assert node1.find(name='dummy') == None
        assert node2.find(name='foo') == None
from mock import Mock, patch, sentinel
from placidity.file import File

def mock_with(mock, file_mock):
    mock.return_value = Mock()
    mock.return_value.__enter__ = Mock()
    mock.return_value.__enter__.return_value = file_mock
    mock.return_value.__exit__ = Mock()

def mock_with_read(mock, read_return=sentinel.file_contents):
    file_mock = Mock()
    file_mock.read.return_value = read_return

    mock_with(mock, file_mock)

class TestFile:

    @patch('__builtin__.open')
    def test_get_file_name(self, open_mock):
        mock_with_read(open_mock)

        file = File('/path/to/file')

        assert file.name == 'file'

    @patch('__builtin__.open')
    def test_get_file_parent(self, open_mock):
        mock_with_read(open_mock)

        file = File('/path/to/file')

        assert file.parent.name == 'to'
        assert file.parent.parent.name == 'path'

    @patch('__builtin__.open')
    def test_get_directory_children(self, open_mock):
        mock_with_read(open_mock)

        file = File('/path/to/file')

        directory = file.parent

        assert directory.children == [file, ]

    @patch('__builtin__.open')
    def test_find_by_name(self, open_mock):
        mock_with_read(open_mock)

        file = File('/path/to/file')

        directory = file.parent

        assert directory.find(name='file') == file

    @patch('__builtin__.open')
    def test_load_python_file(self, open_mock):
        read_return_value = '''
class Bar: flag = True
class Foo: flag = False
        '''
        
        mock_with_read(open_mock, read_return_value)

        file = File(sentinel.filepath)

        assert 'bar' in file.classes
        assert file.classes['bar'].flag == True
        assert 'foo' in file.classes
        assert file.classes['foo'].flag == False
class PluginLoader:

    def load(self, directory):
        ret = []

        for plugin in directory.children:
            plugin_file = plugin.find(name=plugin.name)
            plugin_class = plugin_file.classes[plugin.name]
            ret.append(plugin_class)

        return ret
# -*- coding: utf-8 -*-
class AbstractNode(object):
    def _generic_find(self, node_list_name, **kvargs):
        found_nodes = self._generic_recursion(node_list_name, kvargs, [], [])
        return self._check_found_nodes(found_nodes)

    def _generic_recursion(self, node_list_name, search_clauses, found_nodes,
            visited_nodes):
        visited_nodes.append(self)
        nodes = getattr(self, node_list_name)

        for node in nodes:
            try:
                all_match = True
                for wanted_attribute, wanted_value in search_clauses.items():
                    attribute = getattr(node, wanted_attribute)

                    if attribute != wanted_value:
                        all_match = False
                        break

                if all_match:
                    found_nodes.append(node)
            except AttributeError:
                pass

            if node not in visited_nodes:
                node._generic_recursion(node_list_name, search_clauses,
                    found_nodes, visited_nodes)

        return found_nodes

    def _check_found_nodes(self, found_nodes):
        if len(found_nodes) > 0:
            return found_nodes[0] if len(found_nodes) == 1 else found_nodes

class Node(AbstractNode):

    def __init__(self):
        self.children = NodeContainer(self, complementary_items_name='parents')
        self.parents = NodeContainer(self, complementary_items_name='children')

    def walk(self):
        def _walk(nodes):
            for node in nodes:
                for child in _walk(node.children):
                    yield child

                yield node

        yield self

        for child_walk_node in _walk(self.children):
            yield child_walk_node

    def find_parent_with_attribute(self, attribute):
        return self._find_first_node_with_attribute('parents', attribute, [])

    def _find_first_node_with_attribute(self, node_list_name, attribute,
            visited_nodes):
        visited_nodes.append(self)
        nodes = getattr(self, node_list_name)

        for node in nodes:
            if hasattr(node, attribute):
                return node

            if node not in visited_nodes:
                return node._find_first_node_with_attribute(node_list_name,
                    attribute, visited_nodes)

    def find_child(self, **kvargs):
        return self._generic_find(node_list_name='children', **kvargs)

    def find_parent(self, **kvargs):
        return self._generic_find(node_list_name='parents', **kvargs)

    def find_root(self):
        return self._generic_find(node_list_name='parents', parents=[])


class TreeNode(AbstractNode):

    def __init__(self):
        self.children = NodeContainer(self, complementary_items_name='_parents')
        # XXX: this is bit of a hack but at least it allows to use generic
        # search
        self._parents = NodeContainer(self, complementary_items_name='children')

    @property
    def parent(self):
        return self._parents[0]

    @parent.setter
    def parent(self, value):
        assert len(self._parents) <= 1

        if len(self._parents) == 1:
            self._parents.remove(self._parents[0])
        
        value.children.append(self)

    def find(self, **kvargs):
        return self._generic_find(node_list_name='children', **kvargs)


class NodeContainer(list):

    def __init__(self, owner, complementary_items_name):
        super(NodeContainer, self).__init__()
        self.owner = owner
        self.complementary_items_name = complementary_items_name

    def append(self, *items):
        for item in items:
            if item not in self:
                super(NodeContainer, self).append(item)
                complementary_items = getattr(item,
                    self.complementary_items_name)
                complementary_items.append(self.owner)

    def remove(self, *items):
        for item in items:
            if item in self:
                super(NodeContainer, self).remove(item)
                complementary_items = getattr(item,
                    self.complementary_items_name)
                complementary_items.remove(self.owner)
import inspect
import imp
import os
import tempfile
from node import TreeNode

class File(TreeNode):

    def __init__(self, path=None):
        super(File, self).__init__()

        self.classes = {}

        self.__init_classes(path)
        self.__init_structure(path)

    def __init_classes(self, path):
        with open(path, 'r') as f:
            file_content = f.read()

            # http://docs.python.org/library/tempfile.html#tempfile.mktemp
            temp_file = tempfile.NamedTemporaryFile(delete=False, suffix='.py')
            temp_file.write(file_content)
            temp_file.close()

            try:
                module = imp.load_source('', temp_file.name)
            except Exception, e:
                print e

            module_classes = inspect.getmembers(module, inspect.isclass)

            for name, klass in module_classes:
                self.classes[name.lower()] = klass

            os.unlink(temp_file.name)
            os.unlink(temp_file.name + 'c')

    def __init_structure(self, path):
        if not isinstance(path, str) or not path:
            return

        current_node = self
        parts = path.split('/')

        for part in reversed(parts):
            current_node.name = part
            current_node.parent = File()
            current_node = current_node.parent