def main(global_config, **settings): """ This function returns a Pyramid WSGI application. """ # Setup ------------------------------------------------------------------- # Pyramid Global Settings config = Configurator(settings=settings, root_factory=GlobalRootFactory) # Beaker Session Manager session_factory = pyramid_beaker.session_factory_from_settings(settings) config.set_session_factory(session_factory) # Parse/Convert setting keys that have specifyed datatypes settings = config.registry.settings for key in settings.keys(): settings[key] = convert_str_with_type(settings[key]) # Core Content Mount Tracker ---------------------------------------------- mount_sys = Mount(path=abspath_from_asset_spec('flexi:.')) mount_sys.add_path('assets' , file_filter=regex_file_filter_static) mount_sys.add_path('templates', file_filter=regex_file_filter_template) mount_sys.mounted = tuple(chain(mount_sys._transform_template_list(), mount_sys._transform_static_list(name='assets', path_join=['assets']))) # Addon Content Scan & Trackers ------------------------------------------- settings['content.path.absolute'] = abspath_from_asset_spec(settings['content.path'] ) settings['content.path.addons.absolute'] = abspath_from_asset_spec(settings['content.path.addons']) addon_core = Addon(path=settings['content.path.absolute'], data=dict(name='Core', static_mount='')) settings['addons'] = Addon.scan( path=settings['content.path.addons.absolute'], data_file_regex=settings['content.path.addons.identifyer'] ) addons = list(settings['addons'].values()) + [addon_core] # Core is added last because if it first in the mount order it wont surface the addon content settings['mounts'] = [mount_sys] + addons # Server Researt on change ----------------------------------------------- # Restart the server on content file change # If any of the mounted content files change, then we want the cache.manifest hash to change add_file_callback(lambda: map(operator.attrgetter('absolute'), reduce(operator.add, (mount.get_file_list() for mount in settings['mounts'])))) # Routes ------------------------------------------------------------------ # Static Routes config.add_static_view(name='assets', path=mount_sys.get_path('assets')) #cache_max_age=3600 for addon in addons: config.add_static_view(name='static/{0}'.format(addon.static_mount), path=addon.get_path('static')) settings['mako.directories'] = [ mount_sys.get_path('templates'), ] for addon in addons: settings['mako.directories'].append(addon.get_path('templates')) # View Routes config.add_route('cache_manifest', 'cache.manifest') config.add_route('favicon', 'favicon.ico') # Surpress repeated requests config.add_route('status', 'status') # Views ------------------------------------------------------------------- config.add_view('flexi.views.misc.traversal_template', context='flexi.traversal.TemplateResource') # Events ------------------------------------------------------------------ config.add_subscriber(add_template_helpers_to_event, pyramid.events.BeforeRender) # Register Aditional Includes --------------------------------------------- config.include('pyramid_mako') # The mako.directories value is updated in the scan for addons. We trigger the import here to include the correct folders. # Return ------------------------------------------------------------------ config.scan(ignore='.tests') return config.make_wsgi_app()
def main(global_config, **settings): """ This function returns a Pyramid WSGI application. """ # Setup -------------------------------------------------------------------- # Db init_DBSession(settings) # Pyramid Global Settings config = Configurator(settings=settings) # , autocommit=True # Register Aditional Includes --------------------------------------------- config.include('pyramid_mako') # The mako.directories value is updated in the scan for addons. We trigger the import here to include the correct folders. # Reload on template change template_filenames = map(operator.attrgetter('absolute'), file_scan(config.registry.settings['mako.directories'])) add_file_callback(lambda: template_filenames) # Parse/Convert setting keys that have specifyed datatypes for key in config.registry.settings.keys(): config.registry.settings[key] = convert_str_with_type(config.registry.settings[key]) # i18n config.add_translation_dirs(config.registry.settings['i18n.translation_dirs']) # Session Manager session_settings = extract_subkeys(config.registry.settings, 'session.') session_factory = SignedCookieSessionFactory(serializer=json_serializer, **session_settings) config.set_session_factory(session_factory) # Cachebust etags ---------------------------------------------------------- # crude implementation; count the number of tags in db, if thats changed, the etags will invalidate if not config.registry.settings['server.etag.cache_buster']: from .model.actions import last_update config.registry.settings['server.etag.cache_buster'] = 'last_update:{0}'.format(str(last_update())) # Search Config ------------------------------------------------------------ import karakara.views.search karakara.views.search.search_config = read_json(config.registry.settings['karakara.search.view.config']) # WebSocket ---------------------------------------------------------------- class NullAuthEchoServerManager(object): def recv(self, *args, **kwargs): pass socket_manager = NullAuthEchoServerManager() # Do not activate websocket if in community mode if config.registry.settings.get('karakara.server.mode') == 'comunity': config.registry.settings['karakara.websocket.port'] = None if config.registry.settings.get('karakara.websocket.port'): def authenicator(key): """Only admin authenticated keys can connect to the websocket""" request = Request({'HTTP_COOKIE':'{0}={1}'.format(config.registry.settings['session.cookie_name'],key)}) session_data = session_factory(request) return session_data and session_data.get('admin') try: _socket_manager = AuthEchoServerManager( authenticator=authenicator, websocket_port=config.registry.settings['karakara.websocket.port'], tcp_port=config.registry.settings.get('karakara.tcp.port'), ) _socket_manager.start() socket_manager = _socket_manager except OSError: log.warn('Unable to setup websocket') config.registry['socket_manager'] = socket_manager # Login Providers ---------------------------------------------------------- from .views.comunity_login import social_login social_login.user_store = ComunityUserStore() login_providers = config.registry.settings.get('login.provider.enabled') # Facebook if 'facebook' in login_providers: for settings_key in ('facebook.appid', 'facebook.secret'): assert config.registry.settings.get(settings_key), 'To use facebook as a login provider appid and secret must be provided' social_login.add_login_provider(FacebookLogin( appid=config.registry.settings.get('facebook.appid'), secret=config.registry.settings.get('facebook.secret'), permissions=config.registry.settings.get('facebook.permissions'), )) # Firefox Persona (Deprecated technology but a useful reference) #if 'persona' in login_providers: # social_login.add_login_provider(PersonaLogin( # site_url=config.registry.settings.get('server.url') # )) # No login provider if not login_providers and config.registry.settings.get('karakara.server.mode') == 'development': # Auto login if no service keys are provided social_login.add_login_provider(NullLoginProvider()) social_login.user_store = NullComunityUserStore() template_helpers.javascript_inline['comunity'] = social_login.html_includes # Renderers ---------------------------------------------------------------- # AllanC - currently the auto_format decorator does all the formatting work # it would be far preferable to use the pyramid renderer framework # issue is, we want to set the renderer to be dynamic based on the url given # I don't want to define EVERY method with loads of renderer tags # and I don't want to define 5+ routes for every view callable with differnt formats # We need a nice way of doing this in pyramid, and right now, after HOURS of trawling # the doc and experimenting, I cant find one. #from .renderers.auto_render_factory import AutoRendererFactory, handle_before_render #config.add_renderer(None , AutoRendererFactory) #'renderers.auto_render_factory.auto_renderer_factory' #config.add_renderer('.html', 'pyramid.mako_templating.renderer_factory') #config.add_subscriber(handle_before_render , pyramid.events.BeforeRender) # maybe use this to set renderer? # closeset ive seen # http://zhuoqiang.me/a/restful-pyramid # http://stackoverflow.com/questions/4633320/is-there-a-better-way-to-switch-between-html-and-json-output-in-pyramid # Routes ------------------------------------------------------------------- # Static Routes config.add_static_view(name='ext' , path='../externals/static') #cache_max_age=3600 # settings["static.assets"] config.add_static_view(name='static', path='karakara:{0}'.format(settings["static.assets"])) #cache_max_age=3600 # settings["static.assets"] config.add_static_view(name='player', path=settings["static.player"]) # AllanC - it's official ... static route setup and generation is a mess in pyramid #config.add_static_view(name=settings["static.media" ], path="karakara:media" ) config.add_static_view(name='files' , path=settings["static.processed"]) # Routes def append_format_pattern(route): return re.sub(r'{(.*)}', r'{\1:[^/\.]+}', route) + r'{spacer:[.]?}{format:(%s)?}' % '|'.join(registered_formats()) config.add_route('home' , append_format_pattern('/') ) config.add_route('track' , append_format_pattern('/track/{id}') ) config.add_route('track_list' , append_format_pattern('/track_list') ) config.add_route('queue' , append_format_pattern('/queue') ) config.add_route('priority_tokens', append_format_pattern('/priority_tokens')) config.add_route('fave' , append_format_pattern('/fave') ) config.add_route('message' , append_format_pattern('/message') ) config.add_route('admin_toggle' , append_format_pattern('/admin') ) config.add_route('admin_lock' , append_format_pattern('/admin_lock') ) config.add_route('remote' , append_format_pattern('/remote') ) config.add_route('feedback' , append_format_pattern('/feedback') ) config.add_route('settings' , append_format_pattern('/settings') ) config.add_route('random_images' , append_format_pattern('/random_images') ) config.add_route('inject_testdata' , append_format_pattern('/inject_testdata') ) config.add_route('stats' , append_format_pattern('/stats') ) config.add_route('comunity' , append_format_pattern('/comunity') ) config.add_route('comunity_login', append_format_pattern('/comunity/login')) config.add_route('comunity_logout', append_format_pattern('/comunity/logout')) config.add_route('comunity_list' , append_format_pattern('/comunity/list') ) config.add_route('comunity_track', append_format_pattern('/comunity/track/{id}')) config.add_route('comunity_upload', append_format_pattern('/comunity/upload')) config.add_route('comunity_settings', append_format_pattern('/comunity/settings')) config.add_route('comunity_processmedia_log', append_format_pattern('/comunity/processmedia_log')) config.add_route('search_tags' , '/search_tags/{tags:.*}') config.add_route('search_list' , '/search_list/{tags:.*}') # Upload extras ----- #config.add_static_view(name=settings['upload.route.uploaded'], path=settings['upload.path']) # the 'upload' route above always matchs first config.add_route('upload', '/upload{sep:/?}{name:.*}') # Events ------------------------------------------------------------------- config.add_subscriber(add_localizer_to_request, pyramid.events.NewRequest) config.add_subscriber(add_render_globals_to_template, pyramid.events.BeforeRender) # Return ------------------------------------------------------------------- config.scan(ignore='.tests') config.scan('externals.lib.pyramid_helpers.views') return config.make_wsgi_app()