Example #1
0
    def __new__(cls, name, bases, namespace):
        """
        Construct a new ``Controller`` subclass.

        :param str name: The name of the new class.
        :param bases: A tuple of base classes.
        :type bases: ``tuple`` of classes
        :param dict namespace: The namespace of the new class.

        :returns: A newly constructed subclass of the ``Controller``
                  class.
        """

        # Construct a new Root
        root = elements.Root()

        # Collect delegations
        delegations = {}

        # Walk the namespace looking for elements and callables with
        # Method elements
        for ident, value in namespace.items():
            # Add elements to the root
            if isinstance(value, elements.Element):
                root.add_elem(value, ident)
                continue

            # Add HTTP methods to the root as well
            if hasattr(value, '_micropath_methods'):
                for meth in value._micropath_methods:
                    root.add_elem(meth, ident)

            # Mount the delegation to the root
            if isinstance(value, elements.Delegation):
                if value.element is None:
                    root.mount(value)
                else:
                    root.add_elem(value.element, ident)

                # Add it to the set of delegations
                delegations[ident] = value
                continue

            # Deal with handlers
            if getattr(value, '_micropath_handler', False):
                # If it doesn't have an elem, set it to the root
                if getattr(value, '_micropath_elem', None) is None:
                    value._micropath_elem = root

        # Add the root and handlers list to the namespace
        namespace.update(
            _micropath_root=root,
            _micropath_delegations=[
                delegation for _name, delegation in sorted(delegations.items(),
                                                           key=lambda x: x[0])
            ],
        )

        return super(ControllerMeta, cls).__new__(cls, name, bases, namespace)
Example #2
0
    def test_add_elem_self(self, mocker):
        obj = elements.Root()

        obj.add_elem(obj)

        assert obj.paths == {}
        assert obj.bindings is None
        assert obj.methods == {}
Example #3
0
    def test_init(self, mocker):
        mock_init = mocker.patch.object(
            elements.Element,
            '__init__',
            return_value=None,
        )

        result = elements.Root()

        assert isinstance(result, elements.Root)
        mock_init.assert_called_once_with(None)
Example #4
0
    def test_add_elem_set_ident(self, mocker):
        elem = mocker.Mock(spec=elements.Path, ident=None)
        elem.parent = None
        obj = elements.Root()

        obj.add_elem(elem, 'spam')

        assert obj.paths == {}
        assert obj.bindings is None
        assert obj.methods == {}
        assert elem.ident is None
        assert elem.parent is obj
        elem.set_ident.assert_called_once_with('spam')
Example #5
0
    def test_add_elem_binding_no_ident(self, mocker):
        elem = mocker.Mock(spec=elements.Binding, ident=None)
        elem.parent = None
        obj = elements.Root()

        obj.add_elem(elem)

        assert obj.paths == {}
        assert obj.bindings is None
        assert obj.methods == {}
        assert elem.ident is None
        assert elem.parent is obj
        elem.set_ident.assert_not_called()
Example #6
0
    def test_add_elem_root(self, mocker):
        elem = mocker.Mock(spec=elements.Root, ident=None)
        elem.parent = None
        obj = elements.Root()

        with pytest.raises(ValueError):
            obj.add_elem(elem)
        assert obj.paths == {}
        assert obj.bindings is None
        assert obj.methods == {}
        assert elem.ident is None
        assert elem.parent is None
        elem.set_ident.assert_not_called()
Example #7
0
    def test_add_elem_method(self, mocker):
        elem = mocker.Mock(spec=elements.Method, ident='spam')
        elem.parent = None
        obj = elements.Root()

        obj.add_elem(elem)

        assert obj.paths == {}
        assert obj.bindings is None
        assert obj.methods == {'spam': elem}
        assert elem.ident == 'spam'
        assert elem.parent is obj
        elem.set_ident.assert_not_called()
Example #8
0
    def test_add_elem_method_all_conflict(self, mocker):
        elem = mocker.Mock(spec=elements.Method, ident=None)
        elem.parent = None
        obj = elements.Root()
        obj.methods[None] = 'conflict'

        with pytest.raises(ValueError):
            obj.add_elem(elem)
        assert obj.paths == {}
        assert obj.bindings is None
        assert obj.methods == {None: 'conflict'}
        assert elem.ident is None
        assert elem.parent is None
        elem.set_ident.assert_not_called()
Example #9
0
    def test_add_elem_binding_conflict(self, mocker):
        elem = mocker.Mock(spec=elements.Binding, ident='spam')
        elem.parent = None
        obj = elements.Root()
        obj.bindings = 'conflict'

        with pytest.raises(ValueError):
            obj.add_elem(elem)
        assert obj.paths == {}
        assert obj.bindings == 'conflict'
        assert obj.methods == {}
        assert elem.ident == 'spam'
        assert elem.parent is None
        elem.set_ident.assert_not_called()
Example #10
0
    def test_add_elem_parents(self, mocker):
        elem = mocker.Mock(spec=elements.Path, ident='spam')
        elem.parent = None
        descendant = mocker.Mock(spec=elements.Path, ident=None)
        descendant.parent = elem
        obj = elements.Root()

        obj.add_elem(descendant, 'descendant')

        assert obj.paths == {'spam': elem}
        assert obj.bindings is None
        assert obj.methods == {}
        assert elem.ident == 'spam'
        assert elem.parent is obj
        elem.set_ident.assert_not_called()
        descendant.set_ident.assert_called_once_with('descendant')
Example #11
0
    def test_set_ident(self):
        obj = elements.Root()

        with pytest.raises(ValueError):
            obj.set_ident('ident')