def configure_application(config): """ Configure `sandglass.time` application. """ config.add_translation_dirs('sandglass.time:locales/') config.include('sandglass.time.resource') json_renderer = JSONP(param_name='callback') json_renderer.add_adapter(datetime.datetime, json_datetime_adapter) config.add_renderer('json', json_renderer) # Add custom request methods extend_request_object(config) # Scan modules that need to be pre-loaded config.scan('sandglass.time.models') config.scan('sandglass.time.errorhandlers') # Attach sandglass.time resources to '/time' URL path prefix config.include(include_resources, route_prefix='time')
def main(global_config, **settings): """ This function returns a Pyramid WSGI application. """ authentication_policy = AuthenticationPolicy( settings['auth.secret'], cookie_name='shike.im') authorization_policy = ACLAuthorizationPolicy() config = Configurator(settings=settings) config.set_root_factory('hzsxactivitymanagesite.resources.RootFactory') config.set_authentication_policy(authentication_policy) config.set_authorization_policy(authorization_policy) jsonp = JSONP(param_name='callback') jsonp.add_adapter(ObjectId, objectid_adapter) jsonp.add_adapter(DBRef, dbref_adapter) jsonp.add_adapter(datetime.datetime, datetime_adapter) config.add_renderer('jsonp', jsonp) config.add_subscriber(real_ip_hook, NewRequest) config.set_request_property(get_db, "db", reify=True) config.set_request_property(get_fs, "fs", reify=True) config.set_request_property(get_user, "user", reify=True) config.add_static_view('static', 'static', cache_max_age=3600) config.include("hzsxactivitymanagesite.views.home") config.add_forbidden_view("hzsxactivitymanagesite.views.forbidden_view", renderer="json") config.add_notfound_view("hzsxactivitymanagesite.views.notfound_view", renderer="json") config.add_view("hzsxactivitymanagesite.views.apierror_view", context='hzsxactivitymanagesite.exceptions.APIError', renderer='json') config.add_view("hzsxactivitymanagesite.views.pageerror_view", context='hzsxactivitymanagesite.exceptions.PageError', renderer='error.mako') return config.make_wsgi_app()
} meta = MetadataSchema().serialize(obj.__dict__) # FIXME in_navigation is serialized as string instead of bool meta['in_navigation'] = bools[meta['in_navigation'].lower()] if include_messages: meta['messages'] = get_messages(request) if relmeta: # make data.relationships.meta object rel = dict() relmeta = dict() rel['meta'] = relational_metadata(obj, request) res['relationships'] = rel return dict(data=res, meta=meta) jsonp = JSONP(param_name='callback') jsonp.add_adapter(Content, serialize) jsonp.add_adapter(colander._null, lambda obj, req: None) jsonp.add_adapter(datetime.date, lambda obj, req: str(obj)) jsonp.add_adapter(datetime.datetime, lambda obj, req: obj.isoformat()) jsonp.add_adapter(datetime.time, lambda obj, req: str(obj)) contents_jsonp = JSONP(param_name='callback') def includeme(config): config.add_renderer('kotti_jsonp', jsonp) config.scan(__name__)
def includeme(config): """Upgrading: - register utilities "by hand", after config.include('clld.web.app') - add routes by hand (and remove these from the **kw passed to Configurator) :param config: :return: """ # # now we exploit the default package layout as created via the CLLD scaffold: # # note: the following exploits the import time side effect of modifying the webassets # environment! root_package = config.root_package.__name__ maybe_import('%s.assets' % root_package) pkg_dir = Path(config.root_package.__file__).parent.resolve() json_renderer = JSON() json_renderer.add_adapter(datetime.datetime, lambda obj, req: obj.isoformat()) json_renderer.add_adapter(datetime.date, lambda obj, req: obj.isoformat()) config.add_renderer('json', json_renderer) jsonp_renderer = JSONP(param_name='callback') jsonp_renderer.add_adapter(datetime.datetime, lambda obj, req: obj.isoformat()) jsonp_renderer.add_adapter(datetime.date, lambda obj, req: obj.isoformat()) config.add_renderer('jsonp', jsonp_renderer) config.set_request_factory(ClldRequest) config.registry.registerUtility(CtxFactoryQuery(), interfaces.ICtxFactoryQuery) config.registry.registerUtility(OlacConfig(), interfaces.IOlacConfig) # initialize the db connection engine = engine_from_config(config.registry.settings, 'sqlalchemy.') DBSession.configure(bind=engine) Base.metadata.bind = engine config.add_settings({ 'pyramid.default_locale_name': 'en', 'clld.pkg': root_package, 'clld.parameters': {}}) if 'clld.files' in config.registry.settings: # deployment-specific location of static data files abspath = Path(config.registry.settings['clld.files']).resolve() config.add_settings({'clld.files': abspath}) config.add_static_view('files', abspath.as_posix()) # event subscribers: config.add_subscriber(add_localizer, events.NewRequest) config.add_subscriber(init_map, events.ContextFound) config.add_subscriber( partial(add_renderer_globals, maybe_import('%s.util' % root_package)), events.BeforeRender) # # make it easy to register custom functionality # for name, func in { 'register_datatable': partial(register_cls, interfaces.IDataTable), 'register_map': partial(register_cls, interfaces.IMap), 'register_menu': register_menu, 'register_resource': register_resource, 'register_adapter': register_adapter, 'register_adapters': register_adapters, 'register_download': register_download, 'register_staticresource': register_staticresource, 'add_route_and_view': add_route_and_view, 'add_settings_from_file': add_settings_from_file, 'add_301': add_301, 'add_410': add_410, 'add_page': add_page, 'register_resource_routes_and_views': register_resource_routes_and_views, }.items(): config.add_directive(name, func) # # routes and views # config.add_static_view('clld-static', 'clld:web/static') config.add_static_view('static', '%s:static' % root_package) config.add_route_and_view('_js', '/_js', js, http_cache=3600) # add some maintenance hatches config.add_route_and_view('_raise', '/_raise', _raise) config.add_route_and_view('_ping', '/_ping', _ping, renderer='json') # sitemap support: config.add_route_and_view('robots', '/robots.txt', robots) config.add_route_and_view('sitemapindex', '/sitemap.xml', sitemapindex) config.add_route_and_view('sitemap', '/sitemap.{rsc}.{n}.xml', sitemap) config.add_route('resourcemap', '/resourcemap.json') config.add_view(resourcemap, route_name='resourcemap', renderer='jsonp') config.add_route_and_view( 'select_combination', '/_select_combination', select_combination) config.add_route_and_view('unapi', '/unapi', unapi) config.add_route_and_view('olac', '/olac', olac) config.add_settings_from_file(pkg_dir.joinpath('appconf.ini')) if not config.registry.settings.get('mako.directories'): config.add_settings({'mako.directories': ['clld:web/templates']}) for rsc in RESOURCES: config.register_resource_routes_and_views(rsc) config.register_datatable( rsc.plural, getattr(datatables, rsc.plural.capitalize(), DataTable)) register_resource_adapters(config, rsc) # maps config.register_map('languages', Map) config.register_map('language', LanguageMap) config.register_map('parameter', ParameterMap) config.register_map('combination', CombinationMap) config.include('clld.web.adapters') for icon in ICONS: config.registry.registerUtility(icon, interfaces.IIcon, name=icon.name) config.registry.registerUtility(ORDERED_ICONS, interfaces.IIconList) config.registry.registerUtility(MapMarker(), interfaces.IMapMarker) # # inspect default locations for views and templates: # home_comp = OrderedDict() for name, template in [ ('introduction', False), ('about', False), ('terms', False), ('glossary', False), ('history', False), ('changes', False), ('credits', False), ('legal', True), ('download', True), ('contact', True), ('help', False), ]: home_comp[name] = template if pkg_dir.joinpath('templates').exists(): for p in pkg_dir.joinpath('templates').iterdir(): if p.stem in home_comp and p.suffix == '.mako': home_comp[p.stem] = True for name, template in home_comp.items(): if template: config.add_page(name) config.add_settings({'home_comp': [k for k in home_comp.keys() if home_comp[k]]}) if 'clld.favicon' not in config.registry.settings: favicon = {'clld.favicon': 'clld:web/static/images/favicon.ico'} # hard to test (in particular on travis) and without too much consequence # (and the consequences faced are easy to spot). if pkg_dir.joinpath('static', 'favicon.ico').exists(): # pragma: no cover favicon['clld.favicon'] = root_package + ':static/favicon.ico' config.add_settings(favicon) with open(abspath_from_asset_spec( config.registry.settings['clld.favicon']), mode='rb') as fp: fh = md5() fh.update(fp.read()) config.add_settings({'clld.favicon_hash': fh.hexdigest()}) translation_dirs = ['clld:locale'] if pkg_dir.joinpath('locale').exists(): translation_dirs.append('%s:locale' % root_package) # pragma: no cover config.add_translation_dirs(*translation_dirs) if pkg_dir.joinpath('static/publisher_logo.png').exists(): # pragma: no cover config.add_settings( {'clld.publisher_logo': '%s:static/publisher_logo.png' % root_package}) if asbool(config.registry.settings.get('clld.pacific_centered_maps')): geojson.pacific_centered() v = maybe_import('%s.views' % root_package) if v: config.scan(v) # pragma: no cover menuitems = config.registry.settings.get( 'clld.menuitems_list', ['contributions', 'parameters', 'languages', 'contributors']) config.register_menu(('dataset', dict(label='Home')), *menuitems) config.include('pyramid_mako') for name in ['adapters', 'datatables', 'maps']: mod = maybe_import('%s.%s' % (root_package, name)) if mod and hasattr(mod, 'includeme'): config.include(mod) config.register_download(CldfDownload(common.Dataset, root_package))
def includeme(config): """Upgrading: - register utilities "by hand", after config.include('clld.web.app') - add routes by hand (and remove these from the **kw passed to Configurator) :param config: :return: """ # # now we exploit the default package layout as created via the CLLD scaffold: # # note: the following exploits the import time side effect of modifying the webassets # environment! root_package = config.root_package.__name__ pkg_dir = Path(config.root_package.__file__).parent.resolve() maybe_import('%s.assets' % root_package, pkg_dir=pkg_dir) json_renderer = JSON() json_renderer.add_adapter(datetime.datetime, lambda obj, req: obj.isoformat()) json_renderer.add_adapter(datetime.date, lambda obj, req: obj.isoformat()) config.add_renderer('json', json_renderer) jsonp_renderer = JSONP(param_name='callback') jsonp_renderer.add_adapter(datetime.datetime, lambda obj, req: obj.isoformat()) jsonp_renderer.add_adapter(datetime.date, lambda obj, req: obj.isoformat()) config.add_renderer('jsonp', jsonp_renderer) config.set_request_factory(ClldRequest) config.registry.registerUtility(CtxFactoryQuery(), interfaces.ICtxFactoryQuery) config.registry.registerUtility(OlacConfig(), interfaces.IOlacConfig) config.registry.registerUtility(CldfConfig(), interfaces.ICldfConfig) # initialize the db connection engine = engine_from_config(config.registry.settings, 'sqlalchemy.') DBSession.configure(bind=engine) Base.metadata.bind = engine try: git_tag = git_describe(Path(pkg_dir).parent) except ValueError: # pragma: no cover git_tag = None config.add_settings({ 'pyramid.default_locale_name': 'en', 'clld.pkg': root_package, 'clld.git_tag': git_tag, 'clld.parameters': {} }) if 'clld.files' in config.registry.settings: # deployment-specific location of static data files abspath = Path(config.registry.settings['clld.files']).resolve() config.add_settings({'clld.files': abspath}) config.add_static_view('files', str(abspath)) # event subscribers: config.add_subscriber(add_localizer, events.NewRequest) config.add_subscriber(init_map, events.ContextFound) config.add_subscriber( partial(add_renderer_globals, maybe_import('%s.util' % root_package, pkg_dir=pkg_dir)), events.BeforeRender) # # make it easy to register custom functionality # for name, func in { 'register_utility': register_utility, 'register_datatable': partial(register_cls, interfaces.IDataTable), 'register_map': partial(register_cls, interfaces.IMap), 'register_menu': register_menu, 'register_resource': register_resource, 'register_adapter': register_adapter, 'register_adapters': register_adapters, 'register_download': register_download, 'register_staticresource': register_staticresource, 'add_route_and_view': add_route_and_view, 'add_settings_from_file': add_settings_from_file, 'add_301': add_301, 'add_410': add_410, 'add_page': add_page, 'register_resource_routes_and_views': register_resource_routes_and_views, }.items(): config.add_directive(name, func) # # routes and views # config.add_static_view('clld-static', 'clld:web/static') config.add_static_view('static', '%s:static' % root_package) config.add_route_and_view('_js', '/_js', js, http_cache=3600) # add some maintenance hatches config.add_route_and_view('_raise', '/_raise', _raise) config.add_route_and_view('_ping', '/_ping', _ping, renderer='json') # sitemap support: config.add_route_and_view('robots', '/robots.txt', robots) config.add_route_and_view('sitemapindex', '/sitemap.xml', sitemapindex) config.add_route_and_view('sitemap', '/sitemap.{rsc}.{n}.xml', sitemap) config.add_route('resourcemap', '/resourcemap.json') config.add_view(resourcemap, route_name='resourcemap', renderer='jsonp') config.add_route_and_view('select_combination', '/_select_combination', select_combination) config.add_route_and_view('unapi', '/unapi', unapi) config.add_route_and_view('olac', '/olac', olac) config.add_settings_from_file(pkg_dir.joinpath('appconf.ini')) if not config.registry.settings.get('mako.directories'): config.add_settings({'mako.directories': ['clld:web/templates']}) for rsc in RESOURCES: config.register_resource_routes_and_views(rsc) config.register_datatable( rsc.plural, getattr(datatables, rsc.plural.capitalize(), DataTable)) register_resource_adapters(config, rsc) # maps config.register_map('languages', Map) config.register_map('language', LanguageMap) config.register_map('parameter', ParameterMap) config.register_map('combination', CombinationMap) config.include('clld.web.adapters') for icon in ICONS: config.registry.registerUtility(icon, interfaces.IIcon, name=icon.name) config.registry.registerUtility(ORDERED_ICONS, interfaces.IIconList) config.registry.registerUtility(MapMarker(), interfaces.IMapMarker) # # inspect default locations for views and templates: # home_comp = OrderedDict() for name, template in [ ('introduction', False), ('about', False), ('terms', False), ('glossary', False), ('history', False), ('changes', False), ('credits', False), ('legal', True), ('download', True), ('contact', True), ('help', False), ]: home_comp[name] = template if pkg_dir.joinpath('templates').exists(): for p in pkg_dir.joinpath('templates').iterdir(): if p.stem in home_comp and p.suffix == '.mako': home_comp[p.stem] = True for name, template in home_comp.items(): if template: config.add_page(name) config.add_settings( {'home_comp': [k for k in home_comp.keys() if home_comp[k]]}) if 'clld.favicon' not in config.registry.settings: favicon = {'clld.favicon': 'clld:web/static/images/favicon.ico'} # hard to test (in particular on travis) and without too much consequence # (and the consequences faced are easy to spot). if pkg_dir.joinpath('static', 'favicon.ico').exists(): # pragma: no cover favicon['clld.favicon'] = root_package + ':static/favicon.ico' config.add_settings(favicon) config.add_settings({ 'clld.favicon_hash': md5(abspath_from_asset_spec(config.registry.settings['clld.favicon'])) }) translation_dirs = ['clld:locale'] if pkg_dir.joinpath('locale').exists(): translation_dirs.append('%s:locale' % root_package) # pragma: no cover config.add_translation_dirs(*translation_dirs) if pkg_dir.joinpath( 'static/publisher_logo.png').exists(): # pragma: no cover config.add_settings({ 'clld.publisher_logo': '%s:static/publisher_logo.png' % root_package }) if asbool(config.registry.settings.get('clld.pacific_centered_maps')): geojson.pacific_centered() v = maybe_import('%s.views' % root_package, pkg_dir=pkg_dir) if v: config.scan(v) # pragma: no cover menuitems = config.registry.settings.get( 'clld.menuitems_list', ['contributions', 'parameters', 'languages', 'contributors']) config.register_menu(('dataset', dict(label='Home')), *menuitems) config.include('pyramid_mako') for name in ['adapters', 'datatables', 'maps']: mod = maybe_import('%s.%s' % (root_package, name), pkg_dir=pkg_dir) if mod and hasattr(mod, 'includeme'): config.include(mod) config.register_download(CldfDownload(common.Dataset, root_package))
class Encoder(json.JSONEncoder): def default(self, obj): """Convert ``obj`` to something JSON encoder can handle.""" # if isinstance(obj, NamedTuple): # obj = dict((k, getattr(obj, k)) for k in obj.keys()) if isinstance(obj, decimal.Decimal): return str(obj) elif isinstance(obj, datetime_types): return str(obj) elif obj is colander.null: return None return basedefault(obj) return Encoder def to_json(obj, default=None, **kw): return json.dumps(obj, cls=_encoder(default), **kw) jsonp = JSONP(param_name='callback', serializer=to_json) jsonp.add_adapter(Content, serialize) def includeme(config): config.add_renderer('kotti_jsonp', jsonp) config.scan(__name__)
def create_jsonp_renderer(): renderer = JSONP() renderer.add_adapter(datetime.date, datetime_adapter) renderer.add_adapter(datetime.datetime, datetime_adapter) renderer.add_adapter(Decimal, decimal_adapter) return renderer
def get_configurator(pkg, *utilities, **kw): """ .. seealso:: https://groups.google.com/d/msg/pylons-discuss/Od6qIGaLV6A/3mXVBQ13zWQJ """ kw.setdefault('package', pkg) routes = kw.pop('routes', []) config = Configurator(**kw) json_renderer = JSON() json_renderer.add_adapter(datetime.datetime, lambda obj, req: obj.isoformat()) json_renderer.add_adapter(datetime.date, lambda obj, req: obj.isoformat()) config.add_renderer('json', json_renderer) jsonp_renderer = JSONP(param_name='callback') jsonp_renderer.add_adapter(datetime.datetime, lambda obj, req: obj.isoformat()) jsonp_renderer.add_adapter(datetime.date, lambda obj, req: obj.isoformat()) config.add_renderer('jsonp', jsonp_renderer) for name, pattern in routes: config.add_route(name, pattern) config.set_request_factory(ClldRequest) config.registry.registerUtility(CtxFactoryQuery(), interfaces.ICtxFactoryQuery) config.registry.registerUtility(OlacConfig(), interfaces.IOlacConfig) # initialize the db connection engine = engine_from_config(config.registry.settings, 'sqlalchemy.') DBSession.configure(bind=engine) Base.metadata.bind = engine config.add_settings({ 'pyramid.default_locale_name': 'en', 'clld.pkg': config.package_name, 'clld.parameters': {} }) if 'clld.files' in config.registry.settings: # deployment-specific location of static data files abspath = path(config.registry.settings['clld.files']).abspath() config.add_settings({'clld.files': abspath}) config.add_static_view('files', abspath) # event subscribers: config.add_subscriber(add_localizer, events.NewRequest) config.add_subscriber(init_map, events.ContextFound) config.add_subscriber( partial(add_renderer_globals, maybe_import('%s.util' % config.package_name)), events.BeforeRender) # # make it easy to register custom functionality # for name, func in { 'register_datatable': partial(register_cls, interfaces.IDataTable), 'register_map': partial(register_cls, interfaces.IMap), 'register_menu': register_menu, 'register_resource': register_resource, 'register_adapter': register_adapter, 'register_download': register_download, 'add_route_and_view': add_route_and_view, 'add_settings_from_file': add_settings_from_file, 'add_301': add_301, 'add_410': add_410, }.items(): config.add_directive(name, func) # # routes and views # config.add_static_view('clld-static', 'clld:web/static') config.add_static_view('static', '%s:static' % config.package_name) config.add_route_and_view('_js', '/_js', js, http_cache=3600) # add some maintenance hatches config.add_route_and_view('_raise', '/_raise', _raise) config.add_route_and_view('_ping', '/_ping', _ping, renderer='json') # sitemap support: config.add_route_and_view('robots', '/robots.txt', robots) config.add_route_and_view('sitemapindex', '/sitemap.xml', sitemapindex) config.add_route_and_view('sitemap', '/sitemap.{rsc}.{n}.xml', sitemap) config.add_route('resourcemap', '/resourcemap.json') config.add_view(resourcemap, route_name='resourcemap', renderer='jsonp') config.add_route_and_view('select_combination', '/_select_combination', select_combination) # TODO: remove google site verification for personal account! should be configurable! config.add_route('google-site-verification', 'googlebbc8f4da1abdc58b.html') config.add_view(lambda r: Response( 'google-site-verification: googlebbc8f4da1abdc58b.html'), route_name='google-site-verification') config.add_route_and_view('unapi', '/unapi', unapi) config.add_route_and_view('olac', '/olac', olac) for rsc in RESOURCES: name, model = rsc.name, rsc.model factory = partial(ctx_factory, model, 'index') config.add_route_and_view(rsc.plural, '/%s' % rsc.plural, index_view, factory=factory) config.register_datatable( rsc.plural, getattr(datatables, rsc.plural.capitalize(), DataTable)) config.register_adapter( getattr(excel, rsc.plural.capitalize(), excel.ExcelAdapter), rsc.interface) _kw = dict(factory=partial(ctx_factory, model, 'rsc')) if model == common.Dataset: pattern = '/' _kw['alt_route_pattern'] = '/void.{ext}' else: pattern = '/%s/{id:[^/\.]+}' % rsc.plural config.add_route_and_view(name, pattern, resource_view, **_kw) # maps config.register_map('languages', Map) config.register_map('language', LanguageMap) config.register_map('parameter', ParameterMap) config.register_map('combination', CombinationMap) config.include('clld.web.adapters') for icon in ICONS: config.registry.registerUtility(icon, interfaces.IIcon, name=icon.name) config.registry.registerUtility(MapMarker(), interfaces.IMapMarker) # # now we exploit the default package layout as created via the CLLD scaffold: # # note: the following exploits the import time side effect of modifying the webassets # environment! maybe_import('%s.assets' % config.package_name) pkg_dir = path(config.package.__file__).dirname().abspath() # # inspect default locations for views and templates: # home_comp = OrderedDict() for name, template in [ ('introduction', False), ('about', False), ('terms', False), ('glossary', False), ('history', False), ('changes', False), ('credits', False), ('legal', True), ('download', True), ('contact', True), ('help', False), ]: home_comp[name] = template if pkg_dir.joinpath('templates').exists(): for p in pkg_dir.joinpath('templates').files(): if p.namebase in home_comp and p.ext == '.mako': home_comp[p.namebase] = True views = maybe_import('%s.views' % config.package_name) for name, template in home_comp.items(): if template: config.add_route_and_view(name, '/' + name, getattr(views, name, lambda r: {}), renderer=name + '.mako') config.add_settings( {'home_comp': [k for k in home_comp.keys() if home_comp[k]]}) if 'clld.favicon' not in config.registry.settings: favicon = {'clld.favicon': 'clld:web/static/images/favicon.ico'} # hard to test (in particular on travis) and without too much consequence # (and the consequences faced are easy to spot). if pkg_dir.joinpath('static', 'favicon.ico').exists(): # pragma: no cover favicon[ 'clld.favicon'] = config.package_name + ':static/favicon.ico' config.add_settings(favicon) with open(abspath_from_asset_spec( config.registry.settings['clld.favicon'])) as fp: fh = md5() fh.update(fp.read()) config.add_settings({'clld.favicon_hash': fh.hexdigest()}) if pkg_dir.joinpath('locale').exists(): config.add_translation_dirs('clld:locale', '%s:locale' % config.package_name) if pkg_dir.joinpath( 'static/publisher_logo.png').exists(): # pragma: no cover config.add_settings({ 'clld.publisher_logo': '%s:static/publisher_logo.png' % config.package_name }) config.add_settings_from_file(pkg_dir.joinpath('appconf.ini')) v = maybe_import('%s.views' % config.package_name) if v: config.scan(v) # pragma: no cover menuitems = OrderedDict( dataset=partial(menu_item, 'dataset', label='Home')) for plural in config.registry.settings.get( 'clld.menuitems_list', ['contributions', 'parameters', 'languages', 'contributors']): menuitems[plural] = partial(menu_item, plural) config.registry.registerUtility(menuitems, interfaces.IMenuItems) config.include('pyramid_mako') for utility, interface in utilities: config.registry.registerUtility(utility, interface) return config
def main(global_config, **settings): """ This function returns a Pyramid WSGI application. """ # setup the database engine engine = engine_from_config(settings, 'sqlalchemy.', pool_size=5) sqlahelper.add_engine(engine) # initialize database structures initialize_db(engine) # set up beaker cache set_cache_regions_from_settings(settings) config = Configurator(settings=settings, root_factory=ACLFactory) # mako for templating config.include('pyramid_mako') # Mozilla Persona as the login verifier. It defines default # authentication and authorization policies. config.include('pyramid_persona') # override the authn policy to provide a callback secret = settings.get('persona.secret', None) authn_policy = AuthTktAuthenticationPolicy(secret, callback=groupfinder, hashalg='sha512') config.set_authentication_policy(authn_policy) # for json-encoded responses def datetime_timedelta_adapter(obj, request): return obj.seconds; def datetime_datetime_adapter(obj, request): return obj.isoformat(); def decimal_adapter(obj, request): return float(obj); jsonp = JSONP(param_name='callback') jsonp.add_adapter(datetime.timedelta, datetime_timedelta_adapter) jsonp.add_adapter(datetime.datetime, datetime_datetime_adapter) jsonp.add_adapter(Decimal, decimal_adapter) config.add_renderer('jsonp', jsonp) # for static assets config.add_static_view('static', 'xonstat:static') # robots config.add_route("robots", "robots.txt") config.add_view(robots, route_name="robots") # for 404s config.add_view(notfound, context=HTTPNotFound, renderer="404.mako") # ROOT ROUTE config.add_route("main_index", "/") config.add_view(main_index, route_name="main_index", renderer="main_index.mako") config.add_route("cookies", "/cookies"); config.add_view(cookie_policy, route_name="cookies", renderer="cookies.mako"); config.add_route("recent_games_json", "/recentgames.json") config.add_view(recent_games_json, route_name="recent_games_json", renderer="jsonp") config.add_route("top_servers_json", "/topservers.json") config.add_view(top_servers_json, route_name="top_servers_json", renderer="jsonp") config.add_route("top_maps_json", "/topmaps.json") config.add_view(top_maps_json, route_name="top_maps_json", renderer="jsonp") config.add_route("news_index", "/news") config.add_view(news_index, route_name="news_index", renderer="news_index.mako") config.add_route("forum_index", "/forum") config.add_view(news_index, route_name="forum_index", renderer="news_index.mako") # MAIN SUBMISSION ROUTE config.add_route("submit_stats", "stats/submit") config.add_view(submit_stats, route_name="submit_stats", renderer="jsonp") # PLAYER ROUTES config.add_route("player_game_index", "/player/{player_id:\d+}/games") config.add_view(player_game_index, route_name="player_game_index", renderer="player_game_index.mako") config.add_route("player_game_index_json", "/player/{player_id:\d+}/games.json") config.add_view(player_game_index_json, route_name="player_game_index_json", renderer="jsonp") config.add_route("player_info", "/player/{id:\d+}") config.add_view(player_info, route_name="player_info", renderer="player_info.mako") config.add_route("player_info_json", "/player/{id:\d+}.json") config.add_view(player_info_json, route_name="player_info_json", renderer="jsonp") config.add_route("player_hashkey_info_text", "/player/me") config.add_view(player_hashkey_info_text, route_name="player_hashkey_info_text", renderer="player_hashkey_info_text.mako") config.add_route("player_hashkey_info_json", "/player/me.json") config.add_view(player_hashkey_info_json, route_name="player_hashkey_info_json", renderer="jsonp") config.add_route("player_elo_info_text", "/player/{hashkey}/elo.txt") config.add_view(player_elo_info_text, route_name="player_elo_info_text", renderer="player_elo_info_text.mako") config.add_route("players_elo", "/elo/{hashkeys}"); config.add_view(players_elo, route_name="players_elo", renderer="jsonp") config.add_route("players_elo_b", "/elo_b/{hashkeys}"); config.add_view(players_elo_b, route_name="players_elo_b", renderer="jsonp") config.add_route("players_glicko", "/glicko/{hashkeys}"); config.add_view(players_glicko, route_name="players_glicko", renderer="jsonp") config.add_route("players_aliases_json", "/aliases/{hashkeys}.json"); config.add_view(players_aliases_json, route_name="players_aliases_json", renderer="jsonp") config.add_route("players_aliases_text", "/aliases/{hashkeys}"); config.add_view(players_aliases_text, route_name="players_aliases_text", renderer="players_aliases_text.mako") config.add_route("player_recent_games_json", "/player/{id:\d+}/recent_games.json"); config.add_view(player_recent_games_json, route_name="player_recent_games_json", renderer="jsonp"); # FIXME - needs an additional method to convert to JSON config.add_route("player_elo_info_json", "/player/{hashkey}/elo.json") config.add_view(player_elo_info_json, route_name="player_elo_info_json", renderer="jsonp") config.add_route("player_accuracy", "/player/{id:\d+}/accuracy") config.add_view(player_accuracy_json, route_name="player_accuracy", renderer="jsonp") config.add_route("player_index", "/players") config.add_view(player_index, route_name="player_index", renderer="player_index.mako") config.add_route("player_index_json", "/players.json") config.add_view(player_index_json, route_name="player_index_json", renderer="jsonp") config.add_route("player_captimes", "/player/{player_id:\d+}/captimes") config.add_view(player_captimes, route_name="player_captimes", renderer="player_captimes.mako") config.add_route("player_captimes_json", "/player/{player_id:\d+}/captimes.json") config.add_view(player_captimes_json, route_name="player_captimes_json", renderer="jsonp") config.add_route("player_weaponstats_data_json", "/player/{id:\d+}/weaponstats.json") config.add_view(player_weaponstats_data_json, route_name="player_weaponstats_data_json", renderer="jsonp") config.add_route("top_players_by_time", "/topactive") config.add_view(top_players_by_time, route_name="top_players_by_time", renderer="top_players_by_time.mako") config.add_route("top_servers_by_players", "/topservers") config.add_view(top_servers_by_players, route_name="top_servers_by_players", renderer="top_servers_by_players.mako") config.add_route("top_maps_by_times_played", "/topmaps") config.add_view(top_maps_by_times_played, route_name="top_maps_by_times_played", renderer="top_maps_by_times_played.mako") # GAME ROUTES config.add_route("game_info", "/game/{id:\d+|[0-9a-fA-F]+-[0-9a-fA-F\-]+}") config.add_view(game_info, route_name="game_info", renderer="game_info.mako") config.add_route("game_info_json", "/game/{id:\d+}.json") config.add_view(game_info_json, route_name="game_info_json", renderer="jsonp") config.add_route("rank_index0", "/ranks/{game_type_cd:ctf|ffa|tdm|duel|ca|ft|race|rr|ad}") config.add_view(rank_index, route_name="rank_index0", renderer="rank_index.mako") config.add_route("rank_index", "/ranks/{game_type_cd:ctf|ffa|tdm|duel|ca|ft|race|rr|ad}/{region:\d+}") config.add_view(rank_index, route_name="rank_index", renderer="rank_index.mako") config.add_route("rank_index_json0", "/ranks/{game_type_cd:ctf|ffa|tdm|duel|ca|ft|race|rr|ad}.json") config.add_view(rank_index_json, route_name="rank_index_json0", renderer="jsonp") config.add_route("rank_index_json", "/ranks/{game_type_cd:ctf|ffa|tdm|duel|ca|ft|race|rr|ad}/{region:\d+}.json") config.add_view(rank_index_json, route_name="rank_index_json", renderer="jsonp") config.add_route("game_index", "/games") config.add_view(game_finder, route_name="game_index", renderer="game_finder.mako") # SERVER ROUTES config.add_route("server_index", "/servers") config.add_view(server_index, route_name="server_index", renderer="server_index.mako") config.add_route("server_index_json", "/servers.json") config.add_view(server_index_json, route_name="server_index_json", renderer="jsonp") config.add_route("server_game_index", "/server/{server_id:\d+}/games/page/{page:\d+}") config.add_view(server_game_index, route_name="server_game_index", renderer="server_game_index.mako") config.add_route("server_game_index_json", "/server/{server_id:\d+}/games.json") config.add_view(server_game_index_json, route_name="server_game_index_json", renderer="jsonp") config.add_route("server_info", "/server/{id:\d+|.+\..+:\d+}") config.add_view(server_info, route_name="server_info", renderer="server_info.mako") config.add_route("server_info_json", "/server/{id:\d+|.+\..+:\d+}.json") config.add_view(server_info_json, route_name="server_info_json", renderer="jsonp") # MAP ROUTES config.add_route("map_index", "/maps") config.add_view(map_index, route_name="map_index", renderer="map_index.mako") config.add_route("map_index_json", "/maps.json") config.add_view(map_index_json, route_name="map_index_json", renderer="jsonp") config.add_route("map_info", "/map/{id}") config.add_view(map_info, route_name="map_info", renderer="map_info.mako") config.add_route("map_info_json", "/map/{id:\d+}.json") config.add_view(map_info_json, route_name="map_info_json", renderer="jsonp") config.add_route("map_captimes", "/map/{id:\d+}/captimes") config.add_view(map_captimes, route_name="map_captimes", renderer="map_captimes.mako") config.add_route("map_captimes_json", "/map/{id:\d+}/captimes.json") config.add_view(map_captimes_json, route_name="map_captimes_json", renderer="jsonp") # SEARCH ROUTES config.add_route("search", "search") config.add_view(search, route_name="search", renderer="search.mako") config.add_route("search_json", "search.json") config.add_view(search_json, route_name="search_json", renderer="jsonp") # ADMIN ROUTES config.add_forbidden_view(forbidden, renderer="forbidden.mako") config.add_route("login", "/login") config.add_view(login, route_name="login", check_csrf=True, renderer="json") config.add_route("merge", "/admin/merge") config.add_view(merge, route_name="merge", renderer="merge.mako", permission="merge") return config.make_wsgi_app()
def get_configurator(pkg, *utilities, **kw): """ .. seealso:: https://groups.google.com/d/msg/pylons-discuss/Od6qIGaLV6A/3mXVBQ13zWQJ """ kw.setdefault('package', pkg) routes = kw.pop('routes', []) config = Configurator(**kw) json_renderer = JSON() json_renderer.add_adapter(datetime.datetime, lambda obj, req: obj.isoformat()) json_renderer.add_adapter(datetime.date, lambda obj, req: obj.isoformat()) config.add_renderer('json', json_renderer) jsonp_renderer = JSONP(param_name='callback') jsonp_renderer.add_adapter(datetime.datetime, lambda obj, req: obj.isoformat()) jsonp_renderer.add_adapter(datetime.date, lambda obj, req: obj.isoformat()) config.add_renderer('jsonp', jsonp_renderer) for name, pattern in routes: config.add_route(name, pattern) config.set_request_factory(ClldRequest) config.registry.registerUtility(CtxFactoryQuery(), interfaces.ICtxFactoryQuery) config.registry.registerUtility(OlacConfig(), interfaces.IOlacConfig) # initialize the db connection engine = engine_from_config(config.registry.settings, 'sqlalchemy.') DBSession.configure(bind=engine) Base.metadata.bind = engine config.add_settings({ 'pyramid.default_locale_name': 'en', 'clld.pkg': config.package_name, 'clld.parameters': {}}) if 'clld.files' in config.registry.settings: # deployment-specific location of static data files abspath = path(config.registry.settings['clld.files']).abspath() config.add_settings({'clld.files': abspath}) config.add_static_view('files', abspath) # event subscribers: config.add_subscriber(add_localizer, events.NewRequest) config.add_subscriber(init_map, events.ContextFound) config.add_subscriber( partial(add_renderer_globals, maybe_import('%s.util' % config.package_name)), events.BeforeRender) # # make it easy to register custom functionality # for name, func in { 'register_datatable': partial(register_cls, interfaces.IDataTable), 'register_map': partial(register_cls, interfaces.IMap), 'register_menu': register_menu, 'register_resource': register_resource, 'register_adapter': register_adapter, 'register_download': register_download, 'add_route_and_view': add_route_and_view, 'add_settings_from_file': add_settings_from_file, 'add_301': add_301, 'add_410': add_410, }.items(): config.add_directive(name, func) # # routes and views # config.add_static_view('clld-static', 'clld:web/static') config.add_static_view('static', '%s:static' % config.package_name) config.add_route_and_view('_js', '/_js', js, http_cache=3600) # add some maintenance hatches config.add_route_and_view('_raise', '/_raise', _raise) config.add_route_and_view('_ping', '/_ping', _ping, renderer='json') # sitemap support: config.add_route_and_view('robots', '/robots.txt', robots) config.add_route_and_view('sitemapindex', '/sitemap.xml', sitemapindex) config.add_route_and_view('sitemap', '/sitemap.{rsc}.{n}.xml', sitemap) config.add_route('resourcemap', '/resourcemap.json') config.add_view(resourcemap, route_name='resourcemap', renderer='jsonp') config.add_route_and_view( 'select_combination', '/_select_combination', select_combination) # TODO: remove google site verification for personal account! should be configurable! config.add_route('google-site-verification', 'googlebbc8f4da1abdc58b.html') config.add_view( lambda r: Response('google-site-verification: googlebbc8f4da1abdc58b.html'), route_name='google-site-verification') config.add_route_and_view('unapi', '/unapi', unapi) config.add_route_and_view('olac', '/olac', olac) for rsc in RESOURCES: name, model = rsc.name, rsc.model factory = partial(ctx_factory, model, 'index') config.add_route_and_view( rsc.plural, '/%s' % rsc.plural, index_view, factory=factory) config.register_datatable( rsc.plural, getattr(datatables, rsc.plural.capitalize(), DataTable)) config.register_adapter( getattr(excel, rsc.plural.capitalize(), excel.ExcelAdapter), rsc.interface) kw = dict(factory=partial(ctx_factory, model, 'rsc')) if model == common.Dataset: pattern = '/' kw['alt_route_pattern'] = '/void.{ext}' else: pattern = '/%s/{id:[^/\.]+}' % rsc.plural config.add_route_and_view(name, pattern, resource_view, **kw) # maps config.register_map('languages', Map) config.register_map('language', LanguageMap) config.register_map('parameter', ParameterMap) config.register_map('combination', CombinationMap) config.include('clld.web.adapters') for icon in ICONS: config.registry.registerUtility(icon, interfaces.IIcon, name=icon.name) config.registry.registerUtility(MapMarker(), interfaces.IMapMarker) # # now we exploit the default package layout as created via the CLLD scaffold: # # note: the following exploits the import time side effect of modifying the webassets # environment! maybe_import('%s.assets' % config.package_name) pkg_dir = path(config.package.__file__).dirname().abspath() # # inspect default locations for views and templates: # home_comp = OrderedDict() for name, template in [ ('introduction', False), ('about', False), ('terms', False), ('glossary', False), ('history', False), ('changes', False), ('credits', False), ('legal', True), ('download', True), ('contact', True), ('help', False), ]: home_comp[name] = template if pkg_dir.joinpath('templates').exists(): for p in pkg_dir.joinpath('templates').files(): if p.namebase in home_comp and p.ext == '.mako': home_comp[p.namebase] = True views = maybe_import('%s.views' % config.package_name) for name, template in home_comp.items(): if template: config.add_route_and_view( name, '/' + name, getattr(views, name, lambda r: {}), renderer=name + '.mako') config.add_settings({'home_comp': [k for k in home_comp.keys() if home_comp[k]]}) if 'clld.favicon' not in config.registry.settings: favicon = {'clld.favicon': 'clld:web/static/images/favicon.ico'} # hard to test (in particular on travis) and without too much consequence # (and the consequences faced are easy to spot). if pkg_dir.joinpath('static', 'favicon.ico').exists(): # pragma: no cover favicon['clld.favicon'] = config.package_name + ':static/favicon.ico' config.add_settings(favicon) with open(abspath_from_asset_spec(config.registry.settings['clld.favicon'])) as fp: fh = md5() fh.update(fp.read()) config.add_settings({'clld.favicon_hash': fh.hexdigest()}) if pkg_dir.joinpath('locale').exists(): config.add_translation_dirs('clld:locale', '%s:locale' % config.package_name) if pkg_dir.joinpath('static/publisher_logo.png').exists(): # pragma: no cover config.add_settings( {'clld.publisher_logo': '%s:static/publisher_logo.png' % config.package_name}) config.add_settings_from_file(pkg_dir.joinpath('appconf.ini')) v = maybe_import('%s.views' % config.package_name) if v: config.scan(v) # pragma: no cover menuitems = OrderedDict(dataset=partial(menu_item, 'dataset', label='Home')) for plural in config.registry.settings.get( 'clld.menuitems_list', ['contributions', 'parameters', 'languages', 'contributors'] ): menuitems[plural] = partial(menu_item, plural) config.registry.registerUtility(menuitems, interfaces.IMenuItems) config.include('pyramid_mako') for utility, interface in utilities: config.registry.registerUtility(utility, interface) return config
def main(global_config, **settings): """ This function returns a Pyramid WSGI application. """ # setup the database engine engine = engine_from_config(settings, 'sqlalchemy.', pool_size=5) sqlahelper.add_engine(engine) # initialize database structures initialize_db(engine) # set up beaker cache set_cache_regions_from_settings(settings) config = Configurator(settings=settings, root_factory=ACLFactory) # mako for templating config.include('pyramid_mako') # Mozilla Persona as the login verifier. It defines default # authentication and authorization policies. config.include('pyramid_persona') # override the authn policy to provide a callback secret = settings.get('persona.secret', None) authn_policy = AuthTktAuthenticationPolicy(secret, callback=groupfinder, hashalg='sha512') config.set_authentication_policy(authn_policy) # for json-encoded responses def datetime_timedelta_adapter(obj, request): return obj.seconds def datetime_datetime_adapter(obj, request): return obj.isoformat() def decimal_adapter(obj, request): return float(obj) jsonp = JSONP(param_name='callback') jsonp.add_adapter(datetime.timedelta, datetime_timedelta_adapter) jsonp.add_adapter(datetime.datetime, datetime_datetime_adapter) jsonp.add_adapter(Decimal, decimal_adapter) config.add_renderer('jsonp', jsonp) # for static assets config.add_static_view('static', 'xonstat:static') # robots config.add_route("robots", "robots.txt") config.add_view(robots, route_name="robots") # for 404s config.add_view(notfound, context=HTTPNotFound, renderer="404.mako") # ROOT ROUTE config.add_route("main_index", "/") config.add_view(main_index, route_name="main_index", renderer="main_index.mako") config.add_route("cookies", "/cookies") config.add_view(cookie_policy, route_name="cookies", renderer="cookies.mako") config.add_route("recent_games_json", "/recentgames.json") config.add_view(recent_games_json, route_name="recent_games_json", renderer="jsonp") config.add_route("top_servers_json", "/topservers.json") config.add_view(top_servers_json, route_name="top_servers_json", renderer="jsonp") config.add_route("top_maps_json", "/topmaps.json") config.add_view(top_maps_json, route_name="top_maps_json", renderer="jsonp") config.add_route("news_index", "/news") config.add_view(news_index, route_name="news_index", renderer="news_index.mako") config.add_route("forum_index", "/forum") config.add_view(news_index, route_name="forum_index", renderer="news_index.mako") # MAIN SUBMISSION ROUTE config.add_route("submit_stats", "stats/submit") config.add_view(submit_stats, route_name="submit_stats", renderer="jsonp") # PLAYER ROUTES config.add_route("player_game_index", "/player/{player_id:\d+}/games") config.add_view(player_game_index, route_name="player_game_index", renderer="player_game_index.mako") config.add_route("player_game_index_json", "/player/{player_id:\d+}/games.json") config.add_view(player_game_index_json, route_name="player_game_index_json", renderer="jsonp") config.add_route("player_info", "/player/{id:\d+}") config.add_view(player_info, route_name="player_info", renderer="player_info.mako") config.add_route("player_info_json", "/player/{id:\d+}.json") config.add_view(player_info_json, route_name="player_info_json", renderer="jsonp") config.add_route("player_hashkey_info_text", "/player/me") config.add_view(player_hashkey_info_text, route_name="player_hashkey_info_text", renderer="player_hashkey_info_text.mako") config.add_route("player_hashkey_info_json", "/player/me.json") config.add_view(player_hashkey_info_json, route_name="player_hashkey_info_json", renderer="jsonp") config.add_route("player_elo_info_text", "/player/{hashkey}/elo.txt") config.add_view(player_elo_info_text, route_name="player_elo_info_text", renderer="player_elo_info_text.mako") config.add_route("players_elo", "/elo/{hashkeys}") config.add_view(players_elo, route_name="players_elo", renderer="jsonp") config.add_route("players_elo_b", "/elo_b/{hashkeys}") config.add_view(players_elo_b, route_name="players_elo_b", renderer="jsonp") config.add_route("players_glicko", "/glicko/{hashkeys}") config.add_view(players_glicko, route_name="players_glicko", renderer="jsonp") config.add_route("players_aliases_json", "/aliases/{hashkeys}.json") config.add_view(players_aliases_json, route_name="players_aliases_json", renderer="jsonp") config.add_route("players_aliases_text", "/aliases/{hashkeys}") config.add_view(players_aliases_text, route_name="players_aliases_text", renderer="players_aliases_text.mako") config.add_route("player_recent_games_json", "/player/{id:\d+}/recent_games.json") config.add_view(player_recent_games_json, route_name="player_recent_games_json", renderer="jsonp") # FIXME - needs an additional method to convert to JSON config.add_route("player_elo_info_json", "/player/{hashkey}/elo.json") config.add_view(player_elo_info_json, route_name="player_elo_info_json", renderer="jsonp") config.add_route("player_accuracy", "/player/{id:\d+}/accuracy") config.add_view(player_accuracy_json, route_name="player_accuracy", renderer="jsonp") config.add_route("player_index", "/players") config.add_view(player_index, route_name="player_index", renderer="player_index.mako") config.add_route("player_index_json", "/players.json") config.add_view(player_index_json, route_name="player_index_json", renderer="jsonp") config.add_route("player_captimes", "/player/{player_id:\d+}/captimes") config.add_view(player_captimes, route_name="player_captimes", renderer="player_captimes.mako") config.add_route("player_captimes_json", "/player/{player_id:\d+}/captimes.json") config.add_view(player_captimes_json, route_name="player_captimes_json", renderer="jsonp") config.add_route("player_weaponstats_data_json", "/player/{id:\d+}/weaponstats.json") config.add_view(player_weaponstats_data_json, route_name="player_weaponstats_data_json", renderer="jsonp") config.add_route("top_players_by_time", "/topactive") config.add_view(top_players_by_time, route_name="top_players_by_time", renderer="top_players_by_time.mako") config.add_route("top_servers_by_players", "/topservers") config.add_view(top_servers_by_players, route_name="top_servers_by_players", renderer="top_servers_by_players.mako") config.add_route("top_maps_by_times_played", "/topmaps") config.add_view(top_maps_by_times_played, route_name="top_maps_by_times_played", renderer="top_maps_by_times_played.mako") # GAME ROUTES config.add_route("game_info", "/game/{id:\d+|[0-9a-fA-F]+-[0-9a-fA-F\-]+}") config.add_view(game_info, route_name="game_info", renderer="game_info.mako") config.add_route("game_info_json", "/game/{id:\d+}.json") config.add_view(game_info_json, route_name="game_info_json", renderer="jsonp") config.add_route( "rank_index0", "/ranks/{game_type_cd:ctf|ffa|tdm|duel|ca|ft|race|rr|ad}") config.add_view(rank_index, route_name="rank_index0", renderer="rank_index.mako") config.add_route( "rank_index", "/ranks/{game_type_cd:ctf|ffa|tdm|duel|ca|ft|race|rr|ad}/{region:\d+}") config.add_view(rank_index, route_name="rank_index", renderer="rank_index.mako") config.add_route( "rank_index_json0", "/ranks/{game_type_cd:ctf|ffa|tdm|duel|ca|ft|race|rr|ad}.json") config.add_view(rank_index_json, route_name="rank_index_json0", renderer="jsonp") config.add_route( "rank_index_json", "/ranks/{game_type_cd:ctf|ffa|tdm|duel|ca|ft|race|rr|ad}/{region:\d+}.json" ) config.add_view(rank_index_json, route_name="rank_index_json", renderer="jsonp") config.add_route("game_index", "/games") config.add_view(game_finder, route_name="game_index", renderer="game_finder.mako") # SERVER ROUTES config.add_route("server_index", "/servers") config.add_view(server_index, route_name="server_index", renderer="server_index.mako") config.add_route("server_index_json", "/servers.json") config.add_view(server_index_json, route_name="server_index_json", renderer="jsonp") config.add_route("server_game_index", "/server/{server_id:\d+}/games/page/{page:\d+}") config.add_view(server_game_index, route_name="server_game_index", renderer="server_game_index.mako") config.add_route("server_game_index_json", "/server/{server_id:\d+}/games.json") config.add_view(server_game_index_json, route_name="server_game_index_json", renderer="jsonp") config.add_route("server_info", "/server/{id:\d+|.+\..+:\d+}") config.add_view(server_info, route_name="server_info", renderer="server_info.mako") config.add_route("server_info_json", "/server/{id:\d+|.+\..+:\d+}.json") config.add_view(server_info_json, route_name="server_info_json", renderer="jsonp") # MAP ROUTES config.add_route("map_index", "/maps") config.add_view(map_index, route_name="map_index", renderer="map_index.mako") config.add_route("map_index_json", "/maps.json") config.add_view(map_index_json, route_name="map_index_json", renderer="jsonp") config.add_route("map_info", "/map/{id}") config.add_view(map_info, route_name="map_info", renderer="map_info.mako") config.add_route("map_info_json", "/map/{id:\d+}.json") config.add_view(map_info_json, route_name="map_info_json", renderer="jsonp") config.add_route("map_captimes", "/map/{id:\d+}/captimes") config.add_view(map_captimes, route_name="map_captimes", renderer="map_captimes.mako") config.add_route("map_captimes_json", "/map/{id:\d+}/captimes.json") config.add_view(map_captimes_json, route_name="map_captimes_json", renderer="jsonp") # SEARCH ROUTES config.add_route("search", "search") config.add_view(search, route_name="search", renderer="search.mako") config.add_route("search_json", "search.json") config.add_view(search_json, route_name="search_json", renderer="jsonp") # ADMIN ROUTES config.add_forbidden_view(forbidden, renderer="forbidden.mako") config.add_route("login", "/login") config.add_view(login, route_name="login", check_csrf=True, renderer="json") config.add_route("merge", "/admin/merge") config.add_view(merge, route_name="merge", renderer="merge.mako", permission="merge") return config.make_wsgi_app()
objects, such as datetime and colander.null we solve it here. """ class Encoder(json.JSONEncoder): def default(self, obj): """Convert ``obj`` to something JSON encoder can handle.""" # if isinstance(obj, NamedTuple): # obj = dict((k, getattr(obj, k)) for k in obj.keys()) if isinstance(obj, decimal.Decimal): return str(obj) elif isinstance(obj, datetime_types): return str(obj) elif obj is colander.null: return None return basedefault(obj) return Encoder def to_json(obj, default=None, **kw): return json.dumps(obj, cls=_encoder(default), **kw) jsonp = JSONP(param_name='callback', serializer=to_json) jsonp.add_adapter(Content, serialize) def includeme(config): config.add_renderer('kotti_jsonp', jsonp) config.scan(__name__)