コード例 #1
0
ファイル: test_directive.py プロジェクト: kingel/morepath
def test_json_directive():
    setup()

    app = morepath.App()

    class Model(object):
        def __init__(self, id):
            self.id = id

    def default(request, model):
        return "The view for model: %s" % model.id

    def json(request, model):
        return {'id': model.id}

    c = Config()
    c.action(app, app)
    c.action(app.model(path='{id}',
                       variables=lambda model: {'id': model.id}),
             Model)
    c.action(app.json(model=Model),
             json)
    c.commit()

    c = Client(app, Response)

    response = c.get('/foo')
    assert response.data == '{"id": "foo"}'
コード例 #2
0
ファイル: test_predicates.py プロジェクト: oohlaf/morepath
def test_view_predicates():
    setup()

    app = App()

    class Root(object):
        pass

    def get(request, model):
        return 'GET'

    def post(request, model):
        return 'POST'

    c = Config()
    c.action(app, app)
    c.action(app.root(), Root)
    c.action(app.view(model=Root, name='foo', request_method='GET'), get)
    c.action(app.view(model=Root, name='foo', request_method='POST'), post)

    c.commit()

    c = Client(app, Response)

    response = c.get('/foo')
    assert response.data == 'GET'
    response = c.post('/foo')
    assert response.data == 'POST'
コード例 #3
0
ファイル: test_predicates.py プロジェクト: kingel/morepath
def test_view_predicates():
    setup()

    app = App()

    class Root(object):
        pass

    def get(request, model):
        return 'GET'

    def post(request, model):
        return 'POST'

    c = Config()
    c.action(app, app)
    c.action(app.root(), Root)
    c.action(app.view(model=Root, name='foo', request_method='GET'),
             get)
    c.action(app.view(model=Root, name='foo', request_method='POST'),
             post)

    c.commit()

    c = Client(app, Response)

    response = c.get('/foo')
    assert response.data == 'GET'
    response = c.post('/foo')
    assert response.data == 'POST'
コード例 #4
0
ファイル: test_directive.py プロジェクト: binbrain/morepath
def test_rescan():
    config = setup()

    config.scan(basic)

    config.commit()

    config = setup()

    config.scan(basic)

    class Sub(basic.app):
        testing_config = config

    @Sub.view(model=basic.Model, name='extra')
    def extra(self, request):
        return "extra"

    config.commit()

    c = Client(Sub())

    response = c.get('/1/extra')
    assert response.body == b'extra'

    response = c.get('/1')
    assert response.body == b'The view for model: 1'
コード例 #5
0
ファイル: test_directive.py プロジェクト: kingel/morepath
def test_basic_json():
    setup()
    basic.app.clear()

    config = Config()
    config.scan(basic)
    config.commit()

    c = Client(basic.app, Response)

    response = c.get('/foo/json')

    assert response.data == '{"id": "foo"}'
コード例 #6
0
def test_variable_path_two_variables():
    config = setup()

    class app(morepath.App):
        testing_config = config

    class Model(object):
        def __init__(self, name, version):
            self.name = name
            self.version = version

    @app.path(model=Model, path='{name}-{version}')
    def get_model(name, version):
        return Model(name, version)

    @app.view(model=Model)
    def default(self, request):
        return "View: %s %s" % (self.name, self.version)

    @app.view(model=Model, name='link')
    def link(self, request):
        return request.link(self)

    config.commit()

    c = Client(app())

    response = c.get('/foo-one')
    assert response.body == b'View: foo one'

    response = c.get('/foo-one/link')
    assert response.body == b'http://localhost/foo-one'
コード例 #7
0
ファイル: test_predicates.py プロジェクト: fudomunro/morepath
def test_extra_predicates():
    config = setup()
    app = App(testing_config=config)

    @app.path(path='{id}')
    class Model(object):
        def __init__(self, id):
            self.id = id

    @app.view(model=Model, name='foo', id='a')
    def get_a(self, request):
        return 'a'

    @app.view(model=Model, name='foo', id='b')
    def get_b(self, request):
        return 'b'

    @app.predicate(name='id', order=2, default='')
    def get_id(self, request):
        return self.id
    config.commit()

    c = Client(app)

    response = c.get('/a/foo')
    assert response.body == 'a'
    response = c.get('/b/foo')
    assert response.body == 'b'
コード例 #8
0
def test_url_parameter_list_but_only_one_allowed():
    config = setup()

    class app(morepath.App):
        testing_config = config

    class Model(object):
        def __init__(self, item):
            self.item = item

    @app.path(model=Model, path='/', converters={'item': int})
    def get_model(item):
        return Model(item)

    @app.view(model=Model)
    def default(self, request):
        return repr(self.item)

    @app.view(model=Model, name='link')
    def link(self, request):
        return request.link(self)

    config.commit()

    c = Client(app())

    c.get('/?item=1&item=2', status=400)

    c.get('/link?item=1&item=2', status=400)
コード例 #9
0
def test_extra_parameters():
    config = setup()

    class app(morepath.App):
        testing_config = config

    class Model(object):
        def __init__(self, extra_parameters):
            self.extra_parameters = extra_parameters

    @app.path(model=Model, path='/')
    def get_model(extra_parameters):
        return Model(extra_parameters)

    @app.view(model=Model)
    def default(self, request):
        return repr(sorted(self.extra_parameters.items()))

    @app.view(model=Model, name='link')
    def link(self, request):
        return request.link(self)

    config.commit()

    c = Client(app())

    response = c.get('/?a=A&b=B')
    assert response.body in \
        (b"[(u'a', u'A'), (u'b', u'B')]", b"[('a', 'A'), ('b', 'B')]")
    response = c.get('/link?a=A&b=B')
    assert sorted(response.body[len('http://localhost/?'):].split(b"&")) == [
        b'a=A', b'b=B']
コード例 #10
0
ファイル: test_security.py プロジェクト: reinout/morepath
def test_basic_auth_forget():
    config = setup()
    app = morepath.App(testing_config=config)

    @app.path(path='{id}')
    class Model(object):
        def __init__(self, id):
            self.id = id

    @app.view(model=Model)
    def default(self, request):
        # will not actually do anything as it's a no-op for basic
        # auth, but at least won't crash
        response = Response(content_type='text/plain')
        generic.forget(response, request, lookup=request.lookup)
        return response

    @app.identity_policy()
    def policy():
        return BasicAuthIdentityPolicy()

    config.commit()

    c = Client(app)

    response = c.get('/foo')
    assert response.status == '200 OK'
    assert response.body == ''

    assert sorted(response.headers.items()) == [
        ('Content-Length', '0'),
        ('Content-Type', 'text/plain; charset=UTF-8'),
        ('WWW-Authenticate', 'Basic realm="Realm"'),
        ]
コード例 #11
0
ファイル: test_security.py プロジェクト: reinout/morepath
def test_permission_directive_no_identity():
    config = setup()
    app = morepath.App(testing_config=config)

    class Model(object):
        def __init__(self, id):
            self.id = id

    class Permission(object):
        pass

    @app.path(model=Model, path='{id}',
              variables=lambda model: {'id': model.id})
    def get_model(id):
        return Model(id)

    @app.permission(model=Model, permission=Permission, identity=None)
    def get_permission(identity, model, permission):
        if model.id == 'foo':
            return True
        else:
            return False

    @app.view(model=Model, permission=Permission)
    def default(self, request):
        return "Model: %s" % self.id

    config.commit()

    c = Client(app)

    response = c.get('/foo')
    assert response.body == 'Model: foo'
    response = c.get('/bar')
    assert response.status == '401 Unauthorized'
コード例 #12
0
ファイル: test_security.py プロジェクト: reinout/morepath
def test_no_permission():
    config = setup()
    app = morepath.App(testing_config=config)

    class Model(object):
        def __init__(self, id):
            self.id = id

    class Permission(object):
        pass

    @app.path(model=Model, path='{id}',
              variables=lambda model: {'id': model.id})
    def get_model(id):
        return Model(id)

    @app.view(model=Model, permission=Permission)
    def default(self, request):
        return "Model: %s" % self.id

    config.commit()

    c = Client(app)

    response = c.get('/foo')
    assert response.status == '401 Unauthorized'
コード例 #13
0
ファイル: test_security.py プロジェクト: reinout/morepath
def test_basic_auth_remember():
    config = setup()
    app = morepath.App(testing_config=config)

    @app.path(path='{id}',
              variables=lambda model: {'id': model.id})
    class Model(object):
        def __init__(self, id):
            self.id = id

    @app.view(model=Model)
    def default(self, request):
        # will not actually do anything as it's a no-op for basic
        # auth, but at least won't crash
        response = Response()
        generic.remember(response, request, Identity('foo'),
                         lookup=request.lookup)
        return response

    @app.identity_policy()
    def policy():
        return BasicAuthIdentityPolicy()

    config.commit()

    c = Client(app)

    response = c.get('/foo')
    assert response.status == '200 OK'
    assert response.body == ''
コード例 #14
0
def test_mount_none_should_fail():
    config = setup()

    class app(morepath.App):
        testing_config = config

    class mounted(morepath.App):
        testing_config = config

    @mounted.path(path='')
    class MountedRoot(object):
        pass

    @mounted.view(model=MountedRoot)
    def root_default(self, request):
        return "The root"

    @mounted.view(model=MountedRoot, name='link')
    def root_link(self, request):
        return request.link(self)

    @app.mount(path='{id}', app=mounted)
    def mount_mounted(id):
        return None

    config.commit()

    c = Client(app())

    c.get('/foo', status=404)
    c.get('/foo/link', status=404)
コード例 #15
0
def test_mount_explicit_converters():
    config = setup()

    class app(morepath.App):
        testing_config = config

    class mounted(morepath.App):
        testing_config = config

        def __init__(self, id):
            self.id = id

    class MountedRoot(object):
        def __init__(self, id):
            self.id = id

    @mounted.path(path='', model=MountedRoot)
    def get_root(app):
        return MountedRoot(id=app.id)

    @mounted.view(model=MountedRoot)
    def root_default(self, request):
        return "The root for: %s %s" % (self.id, type(self.id))

    @app.mount(path='{id}', app=mounted, converters=dict(id=int))
    def get_context(id):
        return mounted(id=id)

    config.commit()

    c = Client(app())

    response = c.get('/1')
    assert response.body in \
        (b"The root for: 1 <type 'int'>", b"The root for: 1 <class 'int'>")
コード例 #16
0
def test_mount_child_link_unknown_parent():
    config = setup()

    class app(morepath.App):
        testing_config = config

    class Model(object):
        def __init__(self, id):
            self.id = id

    @app.path(path='')
    class Root(object):
        pass

    @app.view(model=Root)
    def app_root_default(self, request):
        parent = request.app.parent
        if parent is None:
            return 'link error'
        return request.link(Model('one'), app=parent)

    config.commit()

    c = Client(app())

    response = c.get('/')
    assert response.body == b'link error'
コード例 #17
0
def test_mount_sibling_link_at_root_app():
    config = setup()

    class app(morepath.App):
        testing_config = config

    @app.path(path='')
    class Root(object):
        pass

    class Item(object):
        def __init__(self, id):
            self.id = id

    @app.view(model=Root)
    def root_default(self, request):
        sibling = request.app.sibling('foo')
        return request.link(Item(3), app=sibling)

    config.commit()

    c = Client(app())

    with pytest.raises(LinkError):
        c.get('/')
コード例 #18
0
def test_mount_context_parameters():
    config = setup()

    class app(morepath.App):
        testing_config = config

    class mounted(morepath.App):
        testing_config = config

        def __init__(self, mount_id):
            self.mount_id = mount_id

    @mounted.path(path='')
    class MountedRoot(object):
        def __init__(self, app):
            assert isinstance(app.mount_id, int)
            self.mount_id = app.mount_id

    @mounted.view(model=MountedRoot)
    def root_default(self, request):
        return "The root for mount id: %s" % self.mount_id

    @app.mount(path='mounts', app=mounted)
    def get_context(mount_id=0):
        return mounted(mount_id=mount_id)

    config.commit()

    c = Client(app())

    response = c.get('/mounts?mount_id=1')
    assert response.body == b'The root for mount id: 1'
    response = c.get('/mounts')
    assert response.body == b'The root for mount id: 0'
コード例 #19
0
def test_script_name():
    config = setup()

    class app(morepath.App):
        testing_config = config

    class Model(object):
        def __init__(self):
            pass

    @app.path(model=Model, path='simple')
    def get_model():
        return Model()

    @app.view(model=Model)
    def default(self, request):
        return "View"

    @app.view(model=Model, name='link')
    def link(self, request):
        return request.link(self)

    config.commit()

    c = Client(app())

    response = c.get('/prefix/simple',
                     extra_environ=dict(SCRIPT_NAME='/prefix'))
    assert response.body == b'View'

    response = c.get('/prefix/simple/link',
                     extra_environ=dict(SCRIPT_NAME='/prefix'))
    assert response.body == b'http://localhost/prefix/simple'
コード例 #20
0
ファイル: test_directive.py プロジェクト: kingel/morepath
def test_basic():
    setup()
    basic.app.clear()

    config = Config()
    config.scan(basic)
    config.commit()

    c = Client(basic.app, Response)

    response = c.get('/foo')

    assert response.data == 'The view for model: foo'

    response = c.get('/foo/link')
    assert response.data == 'foo'
コード例 #21
0
def test_variable_path_explicit_trumps_implicit():
    config = setup()

    class app(morepath.App):
        testing_config = config

    class Model(object):
        def __init__(self, id):
            self.id = id

    @app.path(model=Model, path='{id}',
              converters=dict(id=Converter(int)))
    def get_model(id='foo'):
        return Model(id)

    @app.view(model=Model)
    def default(self, request):
        return "View: %s (%s)" % (self.id, type(self.id))

    @app.view(model=Model, name='link')
    def link(self, request):
        return request.link(self)

    config.commit()

    c = Client(app())

    response = c.get('/1')
    assert response.body in \
        (b"View: 1 (<type 'int'>)", b"View: 1 (<class 'int'>)")

    response = c.get('/1/link')
    assert response.body == b'http://localhost/1'

    response = c.get('/broken', status=404)
コード例 #22
0
ファイル: test_tween.py プロジェクト: reinout/morepath
def test_tween_directive():
    config = morepath.setup()
    app = morepath.App(testing_config=config)

    @app.path(path='')
    class Root(object):
        pass

    @app.view(model=Root)
    def default(self, request):
        return "View"

    @app.tween_factory()
    def get_modify_response_tween(app, handler):
        def plusplustween(request):
            response = handler(request)
            response.headers['Tween-Header'] = 'FOO'
            return response
        return plusplustween

    config.commit()

    c = Client(app)

    response = c.get('/')
    assert response.body == 'View'
    assert response.headers['Tween-Header'] == 'FOO'
コード例 #23
0
def test_link_for_none_means_no_parameter():
    config = setup()

    class app(morepath.App):
        testing_config = config

    class Model(object):
        def __init__(self, id):
            self.id = id

    @app.path(model=Model, path='')
    def get_model(id):
        return Model(id)

    @app.view(model=Model)
    def default(self, request):
        return "View: %s" % self.id

    @app.view(model=Model, name='link')
    def link(self, request):
        return request.link(self)

    config.commit()

    c = Client(app())

    response = c.get('/')
    assert response.body == b"View: None"

    response = c.get('/link')
    assert response.body == b'http://localhost/'
コード例 #24
0
def test_path_and_url_parameter_converter():
    config = setup()

    class app(morepath.App):
        testing_config = config

    class Model(object):
        def __init__(self, id, param):
            self.id = id
            self.param = param

    from datetime import date

    @app.path(model=Model, path='/{id}', converters=dict(param=date))
    def get_model(id=0, param=None):
        return Model(id, param)

    @app.view(model=Model)
    def default(self, request):
        return "View: %s %s" % (self.id, self.param)

    @app.view(model=Model, name='link')
    def link(self, request):
        return request.link(self)

    config.commit()

    c = Client(app())

    response = c.get('/1/link')
    assert response.body == b'http://localhost/1'
コード例 #25
0
def test_variable_path_one_step():
    config = setup()

    class app(morepath.App):
        testing_config = config

    class Model(object):
        def __init__(self, name):
            self.name = name

    @app.path(model=Model, path='{name}')
    def get_model(name):
        return Model(name)

    @app.view(model=Model)
    def default(self, request):
        return "View: %s" % self.name

    @app.view(model=Model, name='link')
    def link(self, request):
        return request.link(self)

    config.commit()

    c = Client(app())

    response = c.get('/foo')
    assert response.body == b'View: foo'

    response = c.get('/foo/link')
    assert response.body == b'http://localhost/foo'
コード例 #26
0
def test_type_hints_and_converters():
    config = setup()

    class app(morepath.App):
        testing_config = config

    class Model(object):
        def __init__(self, d):
            self.d = d

    from datetime import date

    @app.path(model=Model, path='', converters=dict(d=date))
    def get_model(d):
        return Model(d)

    @app.view(model=Model)
    def default(self, request):
        return "View: %s" % self.d

    @app.view(model=Model, name='link')
    def link(self, request):
        return request.link(self)

    config.commit()

    c = Client(app())

    response = c.get('/?d=20140120')
    assert response.body == b"View: 2014-01-20"

    response = c.get('/link?d=20140120')
    assert response.body == b'http://localhost/?d=20140120'
コード例 #27
0
def test_unknown_explicit_converter():
    config = setup()

    class app(morepath.App):
        testing_config = config

    class Model(object):
        def __init__(self, d):
            self.d = d

    class Unknown(object):
        pass

    @app.path(model=Model, path='/', converters={'d': Unknown})
    def get_model(d):
        return Model(d)

    @app.view(model=Model)
    def default(self, request):
        return "View: %s" % self.d

    @app.view(model=Model, name='link')
    def link(self, request):
        return request.link(self)

    with pytest.raises(DirectiveReportError):
        config.commit()
コード例 #28
0
def test_variable_path_parameter_required_with_default():
    config = setup()

    class app(morepath.App):
        testing_config = config

    class Model(object):
        def __init__(self, id):
            self.id = id

    @app.path(model=Model, path='', required=['id'])
    def get_model(id='b'):
        return Model(id)

    @app.view(model=Model)
    def default(self, request):
        return "View: %s" % self.id

    @app.view(model=Model, name='link')
    def link(self, request):
        return request.link(self)

    config.commit()

    c = Client(app())

    response = c.get('/?id=a')
    assert response.body == b"View: a"

    response = c.get('/', status=400)
コード例 #29
0
def test_simple_path_two_steps():
    config = setup()

    class app(morepath.App):
        testing_config = config

    class Model(object):
        def __init__(self):
            pass

    @app.path(model=Model, path='one/two')
    def get_model():
        return Model()

    @app.view(model=Model)
    def default(self, request):
        return "View"

    @app.view(model=Model, name='link')
    def link(self, request):
        return request.link(self)

    config.commit()

    c = Client(app())

    response = c.get('/one/two')
    assert response.body == b'View'

    response = c.get('/one/two/link')
    assert response.body == b'http://localhost/one/two'
コード例 #30
0
def test_error_when_path_variables_isnt_dict():
    config = setup()

    class App(morepath.App):
        testing_config = config

    class Model(object):
        def __init__(self, id):
            self.store_id = id

    @App.path(model=Model, path='models/{id}',
              variables=lambda m: 'nondict')
    def get_model(id):
        return Model(id)

    @App.view(model=Model)
    def default(self, request):
        return request.link(self)

    config.commit()

    c = Client(App())

    with pytest.raises(LinkError):
        c.get('/models/1')
コード例 #31
0
def test_absorb_path_root():
    config = setup()

    class app(morepath.App):
        testing_config = config

    class Model(object):
        def __init__(self, absorb):
            self.absorb = absorb

    @app.path(model=Model, path='', absorb=True)
    def get_model(absorb):
        return Model(absorb)

    @app.view(model=Model)
    def default(self, request):
        return "A:%s L:%s" % (self.absorb, request.link(self))

    config.commit()

    c = Client(app())

    response = c.get('/a')
    assert response.body == b'A:a L:http://localhost/a'

    response = c.get('/')
    assert response.body == b'A: L:http://localhost/'

    response = c.get('/a/b')
    assert response.body == b'A:a/b L:http://localhost/a/b'
コード例 #32
0
ファイル: test_directive.py プロジェクト: kingel/morepath
def test_nested():
    setup()
    nested.outer_app.clear()
    nested.app.clear()

    config = Config()
    config.scan(nested)
    config.commit()

    c = Client(nested.outer_app, Response)

    response = c.get('/inner/foo')

    assert response.data == 'The view for model: foo'

    response = c.get('/inner/foo/link')
    assert response.data == 'inner/foo'
コード例 #33
0
ファイル: test_directive.py プロジェクト: kingel/morepath
def test_basic_root():
    setup()
    basic.app.clear()

    config = Config()
    config.scan(basic)
    config.commit()

    c = Client(basic.app, Response)

    response = c.get('/')

    assert response.data == 'The root: ROOT'

    # @@ is to make sure we get the view, not the sub-model
    response = c.get('/@@link')
    assert response.data == ''
コード例 #34
0
def wsgi(orm):
    Users.load()

    # morepath.autosetup()
    c = morepath.setup()
    c.scan(damvitool)
    c.commit()

    return staticApp
コード例 #35
0
ファイル: app.py プロジェクト: faassen/morepath_demo
def main():
    # set up morepath's own configuration
    config = morepath.setup()
    # load application specific configuration
    config.scan()
    config.commit()

    # serve app as WSGI app
    waitress.serve(app())
コード例 #36
0
def wsgi(orm):
    with open('etc/users') as f:
        Users.load(f)

    # morepath.autosetup()
    c = morepath.setup()
    c.scan(damvitool)
    c.commit()

    return staticApp
コード例 #37
0
ファイル: test_directive.py プロジェクト: kingel/morepath
def test_imperative():
    setup()

    class Foo(object):
        pass

    @reg.generic
    def target():
        pass

    app = App()

    c = Config()
    c.action(app, app)
    foo = Foo()
    c.action(app.function(target), foo)
    c.commit()

    assert target.component(lookup=app.lookup()) is foo
コード例 #38
0
def test_redirect():
    setup()

    app = morepath.App()

    class Root(object):
        def __init__(self):
            pass

    def default(request, model):
        return morepath.redirect('/')

    c = Config()
    c.action(app, app)
    c.action(app.root(), Root)
    c.action(app.view(model=Root, render=render_html), default)
    c.commit()

    c = Client(app, Response)

    response = c.get('/')
    assert response.status == '302 FOUND'
コード例 #39
0
import morepath

class App(morepath.App):
    pass

@App.path(path='')
class Root(object):
    pass

@App.view(model=Root)
def hello_world(self, request):
    return "Hello world!"

if __name__ == '__main__':
    config = morepath.setup()
    config.scan()
    config.commit()
    morepath.run(App())
コード例 #40
0
ファイル: test_directive.py プロジェクト: kingel/morepath
def test_basic_imperative():
    setup()

    app = morepath.App()

    class Root(object):
        def __init__(self):
            self.value = 'ROOT'

    class Model(object):
        def __init__(self, id):
            self.id = id

    def get_model(id):
        return Model(id)

    def default(request, model):
        return "The view for model: %s" % model.id

    def link(request, model):
        return request.link(model)

    def json(request, model):
        return {'id': model.id}

    def root_default(request, model):
        return "The root: %s" % model.value

    def root_link(request, model):
        return request.link(model)

    c = Config()
    c.action(app, app)
    c.action(app.root(), Root)
    c.action(app.model(model=Model, path='{id}',
                       variables=lambda model: {'id': model.id}),
             get_model)
    c.action(app.view(model=Model),
             default)
    c.action(app.view(model=Model, name='link'),
             link)
    c.action(app.view(model=Model, name='json',
                          render=morepath.render_json),
             json)
    c.action(app.view(model=Root),
             root_default)
    c.action(app.view(model=Root, name='link'),
             root_link)
    c.commit()

    c = Client(app, Response)

    response = c.get('/foo')
    assert response.data == 'The view for model: foo'

    response = c.get('/foo/link')
    assert response.data == 'foo'

    response = c.get('/foo/json')
    assert response.data == '{"id": "foo"}'

    response = c.get('/')
    assert response.data == 'The root: ROOT'

    # @@ is to make sure we get the view, not the sub-model
    response = c.get('/@@link')
    assert response.data == ''
コード例 #41
0
def setup_module(module):
    config = morepath.setup()
    config.scan(restapi)
    config.commit()
コード例 #42
0
ファイル: test_base.py プロジェクト: oohlaf/morepath
def test_base():
    setup()

    class Root(object):
        pass

    class Container(object):
        def __init__(self, id):
            self.id = id
            self.items = {}

        def add_item(self, item_id):
            result = Item(item_id, self)
            self.items[item_id] = result
            return result

    class Item(object):
        def __init__(self, id, parent):
            self.id = id
            self.parent = parent

    alpha = Container('alpha')
    beta = Container('beta')
    alpha.add_item('a')
    alpha.add_item('b')
    c = alpha.add_item('c')
    beta.add_item('d')
    e = beta.add_item('e')

    app = App()

    c = Config()
    c.action(app, app)
    c.action(app.root(), Root)

    def get_container(container_id):
        if container_id == 'alpha':
            return alpha
        elif container_id == 'beta':
            return beta
        return None

    c.action(
        app.model(model=Container,
                  path="{container_id}",
                  variables=lambda container: {'container_id': container.id}),
        get_container)

    def get_item(base, item_id):
        return base.items.get(item_id)

    c.action(
        app.model(model=Item,
                  path="{item_id}",
                  variables=lambda item: {'item_id': item.id},
                  base=Container,
                  get_base=lambda item: item.parent), get_item)

    c.action(app.view(model=Container),
             lambda request, model: 'container: %s' % model.id)
    c.action(app.view(model=Container, name='link'),
             lambda request, model: request.link(model))
    c.action(app.view(model=Item),
             lambda request, model: 'item: %s' % model.id)
    c.action(app.view(model=Item, name='link'),
             lambda request, model: request.link(model))
    c.action(app.view(model=Item, name='otherlink'),
             lambda request, model: request.link(e))
    c.commit()

    c = Client(app, Response)

    response = c.get('/alpha')
    assert response.data == 'container: alpha'
    response = c.get('/beta')
    assert response.data == 'container: beta'
    response = c.get('/alpha/a')
    assert response.data == 'item: a'
    response = c.get('/beta/e')
    assert response.data == 'item: e'
    response = c.get('/alpha/e')
    assert response.status == '404 NOT FOUND'

    response = c.get('/alpha/@@link')
    assert response.data == 'alpha'
    response = c.get('/alpha/a/link')
    assert response.data == 'alpha/a'
    response = c.get('/alpha/a/otherlink')
    assert response.data == 'beta/e'