Пример #1
0
def main(global_config, **settings):
    """ This function returns a Pyramid WSGI application.
    """
    config = get_configurator('autotyp', settings=settings)
    config.include('autotyp.datatables')
    config.include('autotyp.adapters')
    return config.make_wsgi_app()
Пример #2
0
def main(global_config, **settings):
    """ This function returns a Pyramid WSGI application.
    """
    config = get_configurator('clldportal', settings=settings)
    config.scan('clldportal.subscribers')
    config.add_route('lexicalia', '/lexicalia')
    config.add_route('crossgram', '/crossgram')
    return config.make_wsgi_app()
Пример #3
0
def main(global_config, **settings):
    """ This function returns a Pyramid WSGI application.
    """
    settings['clld.pages'] = path(settings['clld.pages'])
    config = get_configurator('jcld', settings=settings)
    config.include('clldmpg')
    config.include('jcld.adapters')
    config.add_route('update_pages', '/_update')
    return config.make_wsgi_app()
Пример #4
0
    def test_get_configurator(self):
        from clld.web.app import get_configurator, menu_item

        class IF(Interface):
            """" """ ""

        config = get_configurator('clld',
                                  settings={'sqlalchemy.url': 'sqlite://'},
                                  routes=[('languages', '/other')])
        # should have no effect, because a resource with this name is registered by
        # default:
        config.register_resource('language', None, None)
        config.register_resource('testresource', Language, IF, with_index=True)
        config.register_download(N3Dump(Language, 'clld'))
Пример #5
0
def main(global_config, **settings):
    """called when bootstrapping a pyramid app using clld/tests/test.ini
    """
    from clld.web.app import get_configurator

    class IF(Interface):
        """" """""

    settings['mako.directories'] = ['clld:web/templates']
    config = get_configurator(
        None, (MapMarker(), interfaces.IMapMarker), settings=settings)
    config.register_adapter(Representation, Mock, name='test')
    config.register_menu(('home', lambda ctx, req: (req.resource_url(req.dataset), 'tt')))
    return config.make_wsgi_app()
Пример #6
0
def main(global_config, **settings):
    """ This function returns a Pyramid WSGI application.
    """
    settings['sitemaps'] = 'contribution parameter source sentence valueset'.split()
    utilities = [
        (ApicsCtxFactoryQuery(), interfaces.ICtxFactoryQuery),
        (ApicsMapMarker(), interfaces.IMapMarker),
        (frequency_marker, interfaces.IFrequencyMarker),
        (link_attrs, interfaces.ILinkAttrs),
    ]
    config = get_configurator('apics', *utilities, **dict(settings=settings))
    config.register_menu(
        ('dataset', partial(menu_item, 'dataset', label='Home')),
        ('contributions', partial(menu_item, 'contributions')),
        ('parameters', partial(menu_item, 'parameters')),
        ('apics_wals', lambda ctx, rq: (rq.route_url('wals_index'), u'WALS\u2013APiCS')),
        ('sentences', partial(menu_item, 'sentences')),
        ('sources', partial(menu_item, 'sources')),
        ('contributors', partial(menu_item, 'contributors')),
    )
    config.register_adapter(GeoJsonFeature, interfaces.IParameter)

    config.registry.registerAdapter(
        FeatureMetadata, (interfaces.IParameter,), interfaces.IRepresentation, name=FeatureMetadata.mimetype)
    for cls in [FeatureBibTex, FeatureTxtCitation, FeatureReferenceManager]:
        for if_ in [interfaces.IRepresentation, interfaces.IMetadata]:
            config.registry.registerAdapter(
                cls, (interfaces.IParameter,), if_, name=cls.mimetype)

    config.register_map('contribution', LanguageMap)
    config.register_map('contributions', LexifierMap)
    config.register_map('parameter', FeatureMap)
    config.register_datatable('parameters', Features)
    config.register_datatable('values', Values)
    config.register_datatable('values_alt', Values)
    config.register_datatable('contributions', ApicsContributions)
    config.register_download(CsvDump(
        common.Language, 'apics', description="Languages as CSV"))
    config.register_download(N3Dump(
        common.Language, 'apics', description="Languages as RDF"))
    #config.register_download(RdfXmlDump(
    #    common.Language, 'apics', description="Languages as RDF"))
    config.register_download(Download(
        common.Source, 'apics', ext='bib', description="Sources as BibTeX"))
    config.register_download(Sqlite(
        common.Dataset, 'apics', description="APiCS database as sqlite3"))
    config.add_route('wals_index', '/wals')
    config.add_route('wals', '/wals/{id}')
    return config.make_wsgi_app()
Пример #7
0
def main(global_config, **settings):
    """called when bootstrapping a pyramid app using clld/tests/test.ini
    """
    from clld.web.app import get_configurator

    class IF(Interface):
        """" """ ""

    settings['mako.directories'] = ['clld:web/templates']
    config = get_configurator(None, (MapMarker(), interfaces.IMapMarker),
                              settings=settings)
    config.register_adapter(Representation, Mock, name='test')
    config.register_menu(('home', lambda ctx, req:
                          (req.resource_url(req.dataset), 'tt')))
    return config.make_wsgi_app()
Пример #8
0
    def test_get_configurator(self):
        from clld.web.app import get_configurator, menu_item

        class IF(Interface):
            """" """""

        config = get_configurator(
            'clld',
            settings={'sqlalchemy.url': 'sqlite://'},
            routes=[('languages', '/other')])
        # should have no effect, because a resource with this name is registered by
        # default:
        config.register_resource('language', None, None)
        config.register_resource('testresource', Language, IF, with_index=True)
        config.register_download(N3Dump(Language, 'clld'))
Пример #9
0
def main(global_config, **settings):
    """ This function returns a Pyramid WSGI application.
    """
    config = get_configurator('crubadan_clld', settings=settings)
    config.include('crubadan_clld.datatables')
    config.include('crubadan_clld.adapters')

    # Set up redundant route to dist files for backwards-compatibility
    config.add_static_view('dist', '/data/crubadan-clld/files')

    # Set up route for OLAC xml file
    # This route overrides clld's builtin 'olac' route
    config.commit() # (bypasses the override error)
    config.add_route_and_view('olac', '/olac.xml', views.olac_xml)
    
    config.register_resource(
        'writingsystem',
        models.WritingSystem,
        interfaces.IWritingSystem,
        with_index=True,
    )

    config.register_menu(
        ('dataset', partial(menu_item, 'dataset', label='Home')),
        ('writingsystems', partial(menu_item, 'writingsystems',
                                    label='Downloads')),
        ('apps', partial(menu_item, 'apps', label='Applications')),
        ('acks', partial(menu_item, 'acks', label='Acknowledgements'))
    )

    config.add_route_and_view(
        'apps',
        '/applications',
        views.apps,
        renderer='apps.mako'
    )

    config.add_route_and_view(
        'acks',
        '/acknowldegments',
        views.acks,
        renderer='acks.mako'
    )

    return config.make_wsgi_app()
Пример #10
0
def main(global_config, **settings):
    """ This function returns a Pyramid WSGI application.
    """
    config = get_configurator('crubadan_clld', settings=settings)
    config.include('crubadan_clld.datatables')
    config.include('crubadan_clld.adapters')

    # Set up redundant route to dist files for backwards-compatibility
    config.add_static_view('dist', '/data/crubadan-clld/files')

    # Set up route for OLAC xml file
    # This route overrides clld's builtin 'olac' route
    config.commit()  # (bypasses the override error)
    config.add_route_and_view('olac', '/olac.xml', views.olac_xml)

    config.register_resource(
        'writingsystem',
        models.WritingSystem,
        interfaces.IWritingSystem,
        with_index=True,
    )

    config.register_menu(
        ('dataset', partial(menu_item, 'dataset', label='Home')),
        ('writingsystems',
         partial(menu_item, 'writingsystems', label='Downloads')),
        ('apps', partial(menu_item, 'apps', label='Applications')),
        ('acks', partial(menu_item, 'acks', label='Acknowledgements')))

    config.add_route_and_view('apps',
                              '/applications',
                              views.apps,
                              renderer='apps.mako')

    config.add_route_and_view('acks',
                              '/acknowldegments',
                              views.acks,
                              renderer='acks.mako')

    return config.make_wsgi_app()
Пример #11
0
def main(global_config, **settings):
    """ This function returns a Pyramid WSGI application.
    """
    config = get_configurator(
        'tsammalex', (TsammalexMapMarker(), IMapMarker), settings=settings)
    config.include('clldmpg')
    config.include('tsammalex.datatables')
    config.include('tsammalex.maps')
    config.include('tsammalex.adapters')
    config.register_menu(
        ('dataset', partial(menu_item, 'dataset', label='Home')),
        ('languages', partial(menu_item, 'languages')),
        ('parameters', partial(menu_item, 'parameters')),
        ('ecoregions', lambda ctx, req: (req.route_url('ecoregions'), 'Ecoregions')),
    )
    config.register_resource('ecoregion', models.Ecoregion, IEcoregion, with_index=True)
    config.register_adapter(
        adapter_factory('ecoregion/detail_html.mako'), IEcoregion)
    config.register_adapter(
        adapter_factory('ecoregion/index_html.mako', base=Index), IEcoregion)

    return config.make_wsgi_app()
Пример #12
0
def main(global_config, **settings):
    """ This function returns a Pyramid WSGI application.
    """
    lc = path(glottolog3.__file__).dirname().joinpath('static', 'legacy_codes.json')
    with open(lc) as fp:
        settings['legacy_codes'] = load(fp)

    settings.update(CFG)
    settings['navbar.inverse'] = True
    settings['route_patterns'] = {
        'languages': '/glottolog',
        'language': '/resource/languoid/id/{id:[^/\.]+}',
        'source': '/resource/reference/id/{id:[^/\.]+}',
        'sources': '/langdoc',
        #'provider': '/langdoc/langdocinformation#provider-{id}',
        'providers': '/langdoc/langdocinformation',
    }
    settings['sitemaps'] = ['language', 'source']
    config = get_configurator(
        'glottolog3',
        (GLCtxFactoryQuery(), ICtxFactoryQuery),
        settings=settings,
        routes=[
            ('languoid.xhtml', '/resource/languoid/id/{id:[^/\.]+}.xhtml'),
            ('reference.xhtml', '/resource/reference/id/{id:[^/\.]+}.xhtml')])
    config.register_menu(
        ('dataset', partial(menu_item, 'dataset', label='Home')),
        ('languages', partial(menu_item, 'languages', label='Languoids')),
        ('sources', partial(menu_item, 'sources', label='Langdoc')),
    )
    config.register_resource('provider', models.Provider, IProvider, with_index=True)
    config.register_adapter(adapters.Redirect, IProvider)
    config.register_adapter(adapters.Bigmap, ILanguage)
    config.register_adapter(adapter_factory('provider/index_html.mako', base=Index), IProvider)
    config.register_datatable('providers', datatables.Providers)

    config.add_view(views.redirect_languoid_xhtml, route_name='languoid.xhtml')
    config.add_view(views.redirect_reference_xhtml, route_name='reference.xhtml')

    config.add_route_and_view(
        'glottolog.meta',
        '/glottolog/glottologinformation',
        views.glottologmeta,
        renderer='glottologmeta.mako')

    config.add_route_and_view(
        'glottolog.families',
        '/glottolog/family',
        views.families,
        renderer='families.mako')

    config.add_route_and_view(
        'glottolog.iso',
        '/resource/languoid/iso/{id:[^/\.]+}',
        views.iso)

    config.add_route_and_view(
        'glottolog.languages',
        '/glottolog/language',
        views.languages,
        renderer='languages.mako')

    config.add_route_and_view(
        'glottolog.childnodes',
        '/db/getchildlects',
        views.childnodes,
        renderer='json')

    config.add_route_and_view(
        'langdoc.complexquery',
        '/langdoc/complexquery',
        views.langdoccomplexquery,
        renderer='langdoccomplexquery.mako')

    for name in 'credits glossary cite downloads errata contact'.split():
        pp = '/' if name == 'credits' else '/meta/'
        config.add_route_and_view(
            'home.' + name,
            pp + name,
            getattr(views, name),
            renderer=name + '.mako')

    config.register_map('language', maps.LanguoidMap)
    config.register_datatable('languages', datatables.Families)
    config.register_datatable('sources', datatables.Refs)

    config.register_download(CsvDump(
        Language, 'glottolog3', description="Languoids as CSV"))
    config.register_download(N3Dump(
        Language, 'glottolog3', description="Languoids as RDF"))
    config.register_download(Download(
        Source, 'glottolog3', ext='bib', description="References as BibTeX"))
    config.register_download(N3Dump(
        Source, 'glottolog3', description="References as RDF"))
    return config.make_wsgi_app()
Пример #13
0
def main(global_config, **settings):
    """ This function returns a Pyramid WSGI application.
    """
    settings['route_patterns'] = {
        'languages': '/languoid',
        'language': '/languoid/lect/wals_code_{id:[^/\.]+}',
        'source': '/refdb/record/{id:[^/\.]+}',
        'sources': '/refdb',
        'familys': '/languoid',
        'family': '/languoid/family/{id:[^/\.]+}',
        'genus': '/languoid/genus/{id:[^/\.]+}',
        'parameters': '/feature',
        'parameter': '/feature/{id:[^/\.]+}',
        'sentences': '/example',
        'sentence': '/example/{id:[^/\.]+}',
        'contributions': '/chapter',
        'contribution': '/chapter/{id:[^/\.]+}',
        'countrys': '/country',
        'country': '/country/{id:[^/\.]+}',
        'contributors': '/author',
        'contributor': '/author/{id:[^/\.]+}',
        'legal': '/about/legal',
        'olac': '/languoid/oai',
        'credits': '/about/credits',
    }
    settings[
        'sitemaps'] = 'contribution parameter source sentence valueset'.split(
        )

    filename_pattern = re.compile('(?P<spec>(c|d|s|f|t)[0-9a-f]{3})\.png')
    icons = []
    for name in sorted(
            path(__file__).dirname().joinpath('static', 'icons').files()):
        m = filename_pattern.match(name.splitall()[-1])
        if m:
            icons.append(WalsIcon(m.group('spec')))

    utilities = [
        (WalsCtxFactoryQuery(), ICtxFactoryQuery),
        (map_marker, IMapMarker),
        (Blog(settings), IBlog),
        (icons, IIconList),
    ]
    config = get_configurator('wals3', *utilities, **dict(settings=settings))
    config.register_menu(
        ('dataset', partial(menu_item, 'dataset', label='Home')),
        ('parameters', partial(menu_item, 'parameters')),
        ('contributions', partial(menu_item, 'contributions')),
        ('languages', partial(menu_item, 'languages')),
        ('sources', partial(menu_item, 'sources')),
        # ('examples', partial(menu_item, 'sentences')),
        ('contributors', partial(menu_item, 'contributors')),
        # ('blog', lambda ctx, req: (req.blog.url('category/news/'), 'Newsblog')),
    )
    config.include('clldmpg')
    config.include('wals3.maps')
    config.include('wals3.datatables')
    config.include('wals3.adapters')

    config.register_resource('family', Family, IFamily)
    config.register_adapter(adapter_factory('family/detail_html.mako'),
                            IFamily)

    config.register_resource('genus', Genus, IGenus)
    config.register_adapter(adapter_factory('genus/detail_html.mako'), IGenus)

    config.register_resource('country', Country, ICountry)
    config.register_adapter(adapter_factory('country/detail_html.mako'),
                            ICountry)

    config.add_route('sample',
                     '/languoid/samples/{count}',
                     factory=sample_factory)

    config.register_adapter(
        adapter_factory('parameter/detail_tab.mako',
                        mimetype='application/vnd.clld.tab',
                        send_mimetype="text/plain",
                        extension='tab',
                        name='tab-separated values'), IParameter)
    config.register_adapter(
        adapter_factory('parameter/detail_xml.mako',
                        mimetype='application/vnd.clld.xml',
                        send_mimetype="application/xml",
                        extension='xml',
                        name='WALS XML',
                        __doc__="Custom XML format."), IParameter)
    config.register_adapter(
        adapter_factory(
            'parameter/detail_georss.mako',
            mimetype='application/vnd.clld.georss+xml',
            send_mimetype="application/rdf+xml",
            extension='georss',
            name="GeoRSS",
            __doc__=
            "RSS with location information (http://en.wikipedia.org/wiki/GeoRSS)."
        ), IParameter)
    config.register_adapter(
        adapter_factory('parameter/detail_kml.mako',
                        mimetype='application/vnd.google-earth.kml+xml',
                        send_mimetype="application/xml",
                        extension='kml',
                        name='KML',
                        __doc__="Keyhole Markup Language"), IParameter)

    config.add_route('feature_info', '/feature-info/{id}')
    config.add_route('genealogy', '/languoid/genealogy')

    config.add_301('/index', lambda req: req.route_url('dataset'))
    config.add_301(
        '/.{ext}',
        lambda req: req.route_url('dataset_alt', ext=req.matchdict['ext']))
    config.add_301(
        '/example/{fid}/all',
        lambda req: req.route_url('parameter', id=req.matchdict['fid']))
    config.add_301(
        '/example/all/wals_code_{lid}',
        lambda req: req.route_url('sentences',
                                  _query=dict(language=req.matchdict['lid'])))

    # we redirect legacy urls for datapoints because they could not be expressed
    # with a single id.
    def datapoint(req):
        data = {k: v for k, v in req.matchdict.items()}
        if data['fid'][-1] not in ascii_uppercase:
            data['fid'] += 'A'
        return req.route_url('valueset',
                             id='%(fid)s-%(lid)s' % data,
                             _query=req.query_params)

    config.add_301('/datapoint/{fid}/wals_code_{lid}',
                   datapoint,
                   name='datapoint')

    # we redirect legacy urls for feature combinations because they could not be expressed
    # with a single id.
    def combined(req):
        return req.route_url('combination',
                             id='%(id1)s_%(id2)s' % req.matchdict,
                             _query=req.query_params)

    config.add_301('/feature/combined/{id1}/{id2}', combined, name='combined')

    config.add_301(
        "/feature/description/{id:[0-9]+}",
        lambda req: req.route_url('contribution', id=req.matchdict['id']))

    config.add_301(
        "/languoid/by_geography",
        lambda req: req.route_url('country', id=req.params.get('country')))

    config.add_301(
        "/wals-2011-{fid}",
        lambda req: req.route_url('parameter', id=req.matchdict.get('fid')))

    config.add_301('/languoid/lect', lambda req: req.route_url('languages'))
    config.add_301('/languoid/family', lambda req: req.route_url('languages'))
    config.add_301('/languoid/genus', lambda req: req.route_url('languages'))
    config.add_301('/supplement/1',
                   lambda req: req.route_url('contribution', id='s1'))
    config.add_301('/supplement/3',
                   lambda req: req.route_url('contribution', id='s1'))
    config.add_301('/supplement/5',
                   lambda req: req.route_url('contribution', id='s5'))
    config.add_301('/supplement/6',
                   lambda req: req.route_url('contribution', id='s6'))
    config.add_301('/supplement/7',
                   lambda req: req.route_url('contribution', id='s7'))
    config.add_301('/supplement/8',
                   lambda req: req.route_url('contribution', id='s8'))
    config.add_301('/supplement/9',
                   lambda req: req.route_url('contribution', id='s9'))

    for pattern in [
            '/refdb/', '/refdb/record', '/refdb/record/', '/refdb/search'
    ]:
        config.add_301(pattern, lambda req: req.route_url('sources'))

    config.add_410('/languoid/osd.{ext}')
    config.add_410("/experimental/{id}")

    config.add_route('olac.source', '/refdb_oai')
    config.add_route('languoids', '/languoids')

    config.register_download(
        Matrix(Language, 'wals3', description="Feature values CSV"))
    config.register_download(
        Download(Source, 'wals3', ext='bib', description="Sources as BibTeX"))
    return config.make_wsgi_app()
Пример #14
0
def main(global_config, **settings):
    """ This function returns a Pyramid WSGI application.
    """
    lc = path(glottolog3.__file__).dirname().joinpath('static',
                                                      'legacy_codes.json')
    with open(lc) as fp:
        settings['legacy_codes'] = load(fp)

    settings.update(CFG)
    settings['navbar.inverse'] = True
    settings['route_patterns'] = {
        'languages': '/glottolog',
        'language': '/resource/languoid/id/{id:[^/\.]+}',
        'source': '/resource/reference/id/{id:[^/\.]+}',
        'sources': '/langdoc',
        #'provider': '/langdoc/langdocinformation#provider-{id}',
        'providers': '/langdoc/langdocinformation',
    }
    settings['sitemaps'] = ['language', 'source']
    config = get_configurator('glottolog3',
                              (GLCtxFactoryQuery(), ICtxFactoryQuery),
                              settings=settings,
                              routes=[
                                  ('languoid.xhtml',
                                   '/resource/languoid/id/{id:[^/\.]+}.xhtml'),
                                  ('reference.xhtml',
                                   '/resource/reference/id/{id:[^/\.]+}.xhtml')
                              ])
    config.register_menu(
        ('dataset', partial(menu_item, 'dataset', label='Home')),
        ('languages', partial(menu_item, 'languages', label='Languoids')),
        ('sources', partial(menu_item, 'sources', label='Langdoc')),
    )
    config.register_resource('provider',
                             models.Provider,
                             IProvider,
                             with_index=True)
    config.register_adapter(adapters.Redirect, IProvider)
    config.register_adapter(adapters.Bigmap, ILanguage)
    config.register_adapter(
        adapter_factory('provider/index_html.mako', base=Index), IProvider)
    config.register_datatable('providers', datatables.Providers)

    config.add_view(views.redirect_languoid_xhtml, route_name='languoid.xhtml')
    config.add_view(views.redirect_reference_xhtml,
                    route_name='reference.xhtml')

    config.add_route_and_view('glottolog.meta',
                              '/glottolog/glottologinformation',
                              views.glottologmeta,
                              renderer='glottologmeta.mako')

    config.add_route_and_view('glottolog.families',
                              '/glottolog/family',
                              views.families,
                              renderer='families.mako')

    config.add_route_and_view('glottolog.iso',
                              '/resource/languoid/iso/{id:[^/\.]+}', views.iso)

    config.add_route_and_view('glottolog.languages',
                              '/glottolog/language',
                              views.languages,
                              renderer='languages.mako')

    config.add_route_and_view('glottolog.childnodes',
                              '/db/getchildlects',
                              views.childnodes,
                              renderer='json')

    config.add_route_and_view('langdoc.complexquery',
                              '/langdoc/complexquery',
                              views.langdoccomplexquery,
                              renderer='langdoccomplexquery.mako')

    for name in 'credits glossary cite downloads errata contact'.split():
        pp = '/' if name == 'credits' else '/meta/'
        config.add_route_and_view('home.' + name,
                                  pp + name,
                                  getattr(views, name),
                                  renderer=name + '.mako')

    config.register_map('language', maps.LanguoidMap)
    config.register_datatable('languages', datatables.Families)
    config.register_datatable('sources', datatables.Refs)

    config.register_download(
        CsvDump(Language, 'glottolog3', description="Languoids as CSV"))
    config.register_download(
        N3Dump(Language, 'glottolog3', description="Languoids as RDF"))
    config.register_download(
        Download(Source,
                 'glottolog3',
                 ext='bib',
                 description="References as BibTeX"))
    config.register_download(
        N3Dump(Source, 'glottolog3', description="References as RDF"))
    return config.make_wsgi_app()
Пример #15
0
def main(global_config, **settings):
    """return a Pyramid WSGI application."""
    settings['route_patterns'] = {
        'languages': '/languoid',
        'language': '/languoid/lect/wals_code_{id:[^/\.]+}',
        'source': '/refdb/record/{id:[^/\.]+}',
        'sources': '/refdb',
        'familys': '/languoid',
        'family': '/languoid/family/{id:[^/\.]+}',
        'genus': '/languoid/genus/{id:[^/\.]+}',
        'parameters': '/feature',
        'parameter': '/feature/{id:[^/\.]+}',
        'sentences': '/example',
        'sentence': '/example/{id:[^/\.]+}',
        'contributions': '/chapter',
        'contribution': '/chapter/{id:[^/\.]+}',
        'countrys': '/country',
        'country': '/country/{id:[^/\.]+}',
        'contributors': '/author',
        'contributor': '/author/{id:[^/\.]+}',
        'legal': '/about/legal',
        'olac': '/languoid/oai',
        'credits': '/about/credits',
    }
    settings['sitemaps'] = 'contribution parameter source sentence valueset'.split()

    filename_pattern = re.compile('(?P<spec>(c|d|s|f|t)[0-9a-f]{3})\.png')
    icons = []
    for name in sorted(
        path(__file__).dirname().joinpath('static', 'icons').files()
    ):
        m = filename_pattern.match(name.splitall()[-1])
        if m:
            icons.append(WalsIcon(m.group('spec')))

    utilities = [
        (WalsCtxFactoryQuery(), ICtxFactoryQuery),
        (map_marker, IMapMarker),
        (Blog(settings), IBlog),
        (icons, IIconList),
    ]
    config = get_configurator('wals3', *utilities, **dict(settings=settings))
    config.register_menu(
        ('dataset', dict(label='Home')),
        'parameters',
        'contributions',
        'languages',
        'sources',
        'contributors',
    )
    config.include('clldmpg')

    config.register_resource('family', Family, IFamily)
    config.register_resource('genus', Genus, IGenus)
    config.register_resource('country', Country, ICountry)

    config.add_route(
        'sample_alt', '/languoid/samples/{count}.{ext}', factory=sample_factory)
    config.add_route(
        'sample', '/languoid/samples/{count}', factory=sample_factory)

    for spec in [
        dict(
            template='parameter/detail_tab.mako',
            mimetype='application/vnd.clld.tab',
            send_mimetype="text/plain",
            extension='tab',
            name='tab-separated values'),
        dict(
            template='parameter/detail_xml.mako',
            mimetype='application/vnd.clld.xml',
            send_mimetype="application/xml",
            extension='xml',
            name='WALS XML',
            __doc__="Custom XML format."),
        dict(
            template='parameter/detail_georss.mako',
            mimetype='application/vnd.clld.georss+xml',
            send_mimetype="application/rdf+xml",
            extension='georss',
            name="GeoRSS",
            __doc__="RSS with location information "
                    "(http://en.wikipedia.org/wiki/GeoRSS)."),
        dict(
            template='parameter/detail_kml.mako',
            mimetype='application/vnd.google-earth.kml+xml',
            send_mimetype="application/xml",
            extension='kml',
            name='KML',
            __doc__="Keyhole Markup Language"),
    ]:
        config.register_adapter(spec, IParameter)

    config.add_route('feature_info', '/feature-info/{id}')
    config.add_route('genealogy', '/languoid/genealogy')

    config.add_301(
        '/index',
        lambda req: req.route_url('dataset'))
    config.add_301(
        '/.{ext}',
        lambda req: req.route_url('dataset_alt', ext=req.matchdict['ext']))
    config.add_301(
        '/example/{fid}/all',
        lambda req: req.route_url('parameter', id=req.matchdict['fid']))
    config.add_301(
        '/example/all/wals_code_{lid}',
        lambda req: req.route_url(
            'sentences', _query=dict(language=req.matchdict['lid'])))

    # we redirect legacy urls for datapoints because they could not be expressed
    # with a single id.
    def datapoint(req):
        data = {k: v for k, v in req.matchdict.items()}
        if data['fid'][-1] not in ascii_uppercase:
            data['fid'] += 'A'
        return req.route_url(
            'valueset', id='%(fid)s-%(lid)s' % data, _query=req.query_params)

    config.add_301('/datapoint/{fid}/wals_code_{lid}', datapoint, name='datapoint')

    # we redirect legacy urls for feature combinations because they could not be expressed
    # with a single id.
    def combined(req):
        return req.route_url(
            'combination', id='%(id1)s_%(id2)s' % req.matchdict, _query=req.query_params)

    config.add_301('/feature/combined/{id1}/{id2}', combined, name='combined')

    config.add_301(
        "/feature/description/{id:[0-9]+}",
        lambda req: req.route_url('contribution', id=req.matchdict['id']))

    config.add_301(
        "/languoid/by_geography",
        lambda req: req.route_url('country', id=req.params.get('country')))

    config.add_301(
        "/wals-2011-{fid}",
        lambda req: req.route_url('parameter', id=req.matchdict.get('fid')))

    config.add_301('/languoid/lect', lambda req: req.route_url('languages'))
    config.add_301('/languoid/family', lambda req: req.route_url('languages'))
    config.add_301('/languoid/genus', lambda req: req.route_url('languages'))
    config.add_301('/supplement/1', lambda req: req.route_url('contribution', id='s1'))
    config.add_301('/supplement/3', lambda req: req.route_url('contribution', id='s1'))
    config.add_301('/supplement/5', lambda req: req.route_url('contribution', id='s5'))
    config.add_301('/supplement/6', lambda req: req.route_url('contribution', id='s6'))
    config.add_301('/supplement/7', lambda req: req.route_url('contribution', id='s7'))
    config.add_301('/supplement/8', lambda req: req.route_url('contribution', id='s8'))
    config.add_301('/supplement/9', lambda req: req.route_url('contribution', id='s9'))

    for pattern in ['/refdb/', '/refdb/record', '/refdb/record/', '/refdb/search']:
        config.add_301(pattern, lambda req: req.route_url('sources'))

    config.add_410('/languoid/osd.{ext}')
    config.add_410("/experimental/{id}")

    config.add_route('olac.source', '/refdb_oai')
    config.add_route('languoids', '/languoids')

    config.register_download(
        Matrix(Language, 'wals3', description="Feature values CSV"))
    config.register_download(
        Download(Source, 'wals3', ext='bib', description="Sources as BibTeX"))
    return config.make_wsgi_app()