def make_app(global_conf, full_stack=True, static_files=True, **app_conf): """Create a Pylons WSGI application and return it ``global_conf`` The inherited configuration for this application. Normally from the [DEFAULT] section of the Paste ini file. ``full_stack`` Whether this application provides a full WSGI stack (by default, meaning it handles its own exceptions and errors). Disable full_stack when this application is "managed" by another WSGI middleware. ``static_files`` Whether this application serves its own static files; disable when another web server is responsible for serving them. ``app_conf`` The application's local configuration. Normally specified in the [app:<name>] section of the Paste ini file (where <name> defaults to main). """ # Configure the Pylons environment config = load_environment(global_conf, app_conf) alembic_migrations = MediaCoreMigrator.from_config(config, log=log) if alembic_migrations.is_db_scheme_current(): events.Environment.database_ready() else: log.warn( 'Running with an outdated database scheme. Please upgrade your database.' ) plugin_mgr = config['pylons.app_globals'].plugin_mgr # The Pylons WSGI app app = PylonsApp(config=config) # Allow the plugin manager to tweak our WSGI app app = plugin_mgr.wrap_pylons_app(app) # Routing/Session/Cache Middleware app = RoutesMiddleware(app, config['routes.map'], singleton=False) app = SessionMiddleware(app, config) # CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares) # add repoze.who middleware with our own authorization library app = add_auth(app, config) # ToscaWidgets Middleware app = setup_tw_middleware(app, config) # Strip the name of the .fcgi script, if using one, from the SCRIPT_NAME app = FastCGIScriptStripperMiddleware(app) # If enabled, set up the proxy prefix for routing behind # fastcgi and mod_proxy based deployments. if config.get('proxy_prefix', None): app = setup_prefix_middleware(app, global_conf, config['proxy_prefix']) # END CUSTOM MIDDLEWARE if asbool(full_stack): # Handle Python exceptions app = ErrorHandler(app, global_conf, **config['pylons.errorware']) # by default Apache uses a global alias for "/error" in the httpd.conf # which means that users can not send error reports through MediaCore's # error page (because that POSTs to /error/report). # To make things worse Apache (at least up to 2.4) has no "unalias" # functionality. So we work around the issue by using the "/errors" # prefix (extra "s" at the end) error_path = '/errors/document' # Display error documents for 401, 403, 404 status codes (and # 500 when debug is disabled) if asbool(config['debug']): app = StatusCodeRedirect(app, path=error_path) else: app = StatusCodeRedirect(app, errors=(400, 401, 403, 404, 500), path=error_path) # Cleanup the DBSession only after errors are handled app = DBSessionRemoverMiddleware(app) # Establish the Registry for this application app = RegistryManager(app) app = setup_db_sanity_checks(app, config) if asbool(static_files): # Serve static files from our public directory public_app = StaticURLParser(config['pylons.paths']['static_files']) static_urlmap = URLMap() # Serve static files from all plugins for dir, path in plugin_mgr.public_paths().iteritems(): static_urlmap[dir] = StaticURLParser(path) # Serve static media and podcast images from outside our public directory for image_type in ('media', 'podcasts'): dir = '/images/' + image_type path = os.path.join(config['image_dir'], image_type) static_urlmap[dir] = StaticURLParser(path) # Serve appearance directory outside of public as well dir = '/appearance' path = os.path.join(config['app_conf']['cache_dir'], 'appearance') static_urlmap[dir] = StaticURLParser(path) # We want to serve goog closure code for debugging uncompiled js. if config['debug']: goog_path = os.path.join(config['pylons.paths']['root'], '..', 'closure-library', 'closure', 'goog') if os.path.exists(goog_path): static_urlmap['/scripts/goog'] = StaticURLParser(goog_path) app = Cascade([public_app, static_urlmap, app]) if asbool(config.get('enable_gzip', 'true')): app = setup_gzip_middleware(app, global_conf) app.config = config return app
def make_app(global_conf, full_stack=True, static_files=True, **app_conf): """Create a Pylons WSGI application and return it ``global_conf`` The inherited configuration for this application. Normally from the [DEFAULT] section of the Paste ini file. ``full_stack`` Whether this application provides a full WSGI stack (by default, meaning it handles its own exceptions and errors). Disable full_stack when this application is "managed" by another WSGI middleware. ``static_files`` Whether this application serves its own static files; disable when another web server is responsible for serving them. ``app_conf`` The application's local configuration. Normally specified in the [app:<name>] section of the Paste ini file (where <name> defaults to main). """ # Configure the Pylons environment config = load_environment(global_conf, app_conf) alembic_migrations = MediaCoreMigrator.from_config(config, log=log) if alembic_migrations.is_db_scheme_current(): events.Environment.database_ready() else: log.warn('Running with an outdated database scheme. Please upgrade your database.') plugin_mgr = config['pylons.app_globals'].plugin_mgr # The Pylons WSGI app app = PylonsApp(config=config) # Allow the plugin manager to tweak our WSGI app app = plugin_mgr.wrap_pylons_app(app) # Routing/Session/Cache Middleware app = RoutesMiddleware(app, config['routes.map'], singleton=False) app = SessionMiddleware(app, config) # CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares) # add repoze.who middleware with our own authorization library app = add_auth(app, config) # ToscaWidgets Middleware app = setup_tw_middleware(app, config) # Strip the name of the .fcgi script, if using one, from the SCRIPT_NAME app = FastCGIScriptStripperMiddleware(app) # If enabled, set up the proxy prefix for routing behind # fastcgi and mod_proxy based deployments. if config.get('proxy_prefix', None): app = setup_prefix_middleware(app, global_conf, config['proxy_prefix']) # END CUSTOM MIDDLEWARE if asbool(full_stack): # Handle Python exceptions app = ErrorHandler(app, global_conf, **config['pylons.errorware']) # by default Apache uses a global alias for "/error" in the httpd.conf # which means that users can not send error reports through MediaCore's # error page (because that POSTs to /error/report). # To make things worse Apache (at least up to 2.4) has no "unalias" # functionality. So we work around the issue by using the "/errors" # prefix (extra "s" at the end) error_path = '/errors/document' # Display error documents for 401, 403, 404 status codes (and # 500 when debug is disabled) if asbool(config['debug']): app = StatusCodeRedirect(app, path=error_path) else: app = StatusCodeRedirect(app, errors=(400, 401, 403, 404, 500), path=error_path) # Cleanup the DBSession only after errors are handled app = DBSessionRemoverMiddleware(app) # Establish the Registry for this application app = RegistryManager(app) app = setup_db_sanity_checks(app, config) if asbool(static_files): # Serve static files from our public directory public_app = StaticURLParser(config['pylons.paths']['static_files']) static_urlmap = URLMap() # Serve static files from all plugins for dir, path in plugin_mgr.public_paths().iteritems(): static_urlmap[dir] = StaticURLParser(path) # Serve static media and podcast images from outside our public directory for image_type in ('media', 'podcasts'): dir = '/images/' + image_type path = os.path.join(config['image_dir'], image_type) static_urlmap[dir] = StaticURLParser(path) # Serve appearance directory outside of public as well dir = '/appearance' path = os.path.join(config['app_conf']['cache_dir'], 'appearance') static_urlmap[dir] = StaticURLParser(path) # We want to serve goog closure code for debugging uncompiled js. if config['debug']: goog_path = os.path.join(config['pylons.paths']['root'], '..', 'closure-library', 'closure', 'goog') if os.path.exists(goog_path): static_urlmap['/scripts/goog'] = StaticURLParser(goog_path) app = Cascade([public_app, static_urlmap, app]) if asbool(config.get('enable_gzip', 'true')): app = setup_gzip_middleware(app, global_conf) app.config = config return app
def setup_app(command, conf, vars): """Called by ``paster setup-app``. This script is responsible for: * Creating the initial database schema and loading default data. * Executing any migrations necessary to bring an existing database up-to-date. Your data should be safe but, as always, be sure to make backups before using this. * Re-creating the default database for every run of the test suite. XXX: All your data will be lost IF you run the test suite with a config file named 'test.ini'. Make sure you have this configured to a different database than in your usual deployment.ini or development.ini file because all database tables are dropped a and recreated every time this script runs. XXX: If you are upgrading from MediaCore v0.7.2 or v0.8.0, run whichever one of these that applies: ``python batch-scripts/upgrade/upgrade_from_v072.py deployment.ini`` ``python batch-scripts/upgrade/upgrade_from_v080.py deployment.ini`` XXX: For search to work, we depend on a number of MySQL triggers which copy the data from our InnoDB tables to a MyISAM table for its fulltext indexing capability. Triggers can only be installed with a mysql superuser like root, so you must run the setup_triggers.sql script yourself. """ config = load_environment(conf.global_conf, conf.local_conf) plugin_manager = config["pylons.app_globals"].plugin_mgr mediacore_migrator = MediaCoreMigrator.from_config(conf, log=log) engine = metadata.bind db_connection = engine.connect() # simplistic check to see if MediaCore tables are present, just check for # the media_files table and assume that all other tables are there as well from mediacore.model.media import media_files mediacore_tables_exist = engine.dialect.has_table(db_connection, media_files.name) run_migrations = True if not mediacore_tables_exist: head_revision = mediacore_migrator.head_revision() log.info("Initializing new database with version %r" % head_revision) metadata.create_all(bind=DBSession.bind, checkfirst=True) mediacore_migrator.init_db(revision=head_revision) run_migrations = False add_default_data() for migrator in plugin_manager.migrators(): migrator.init_db() events.Environment.database_initialized() elif not mediacore_migrator.migrate_table_exists(): log.error( "No migration table found, probably your MediaCore install " "is too old (< 0.9?). Please upgrade to MediaCore CE 0.9 first." ) raise AssertionError("no migration table found") elif not mediacore_migrator.alembic_table_exists(): alembic_revision = mediacore_migrator.map_migrate_version() mediacore_migrator.stamp(alembic_revision) if run_migrations: mediacore_migrator.migrate_db() for migrator in plugin_manager.migrators(): migrator.migrate_db() events.Environment.database_migrated() cleanup_players_table(enabled=True) # Save everything, along with the dummy data if applicable DBSession.commit() events.Environment.database_ready() log.info("Generating appearance.css from your current settings") settings = DBSession.query(Setting.key, Setting.value) generate_appearance_css(settings, cache_dir=conf["cache_dir"]) log.info("Successfully setup")
def setup_app(command, conf, vars): """Called by ``paster setup-app``. This script is responsible for: * Creating the initial database schema and loading default data. * Executing any migrations necessary to bring an existing database up-to-date. Your data should be safe but, as always, be sure to make backups before using this. * Re-creating the default database for every run of the test suite. XXX: All your data will be lost IF you run the test suite with a config file named 'test.ini'. Make sure you have this configured to a different database than in your usual deployment.ini or development.ini file because all database tables are dropped a and recreated every time this script runs. XXX: If you are upgrading from MediaCore v0.7.2 or v0.8.0, run whichever one of these that applies: ``python batch-scripts/upgrade/upgrade_from_v072.py deployment.ini`` ``python batch-scripts/upgrade/upgrade_from_v080.py deployment.ini`` XXX: For search to work, we depend on a number of MySQL triggers which copy the data from our InnoDB tables to a MyISAM table for its fulltext indexing capability. Triggers can only be installed with a mysql superuser like root, so you must run the setup_triggers.sql script yourself. """ config = load_environment(conf.global_conf, conf.local_conf) plugin_manager = config['pylons.app_globals'].plugin_mgr mediacore_migrator = MediaCoreMigrator.from_config(conf, log=log) engine = metadata.bind db_connection = engine.connect() # simplistic check to see if MediaCore tables are present, just check for # the media_files table and assume that all other tables are there as well from mediacore.model.media import media_files mediacore_tables_exist = engine.dialect.has_table(db_connection, media_files.name) run_migrations = True if not mediacore_tables_exist: head_revision = mediacore_migrator.head_revision() log.info('Initializing new database with version %r' % head_revision) metadata.create_all(bind=DBSession.bind, checkfirst=True) mediacore_migrator.init_db(revision=head_revision) run_migrations = False add_default_data() for migrator in plugin_manager.migrators(): migrator.init_db() events.Environment.database_initialized() elif not mediacore_migrator.migrate_table_exists(): log.error('No migration table found, probably your MediaCore install ' 'is too old (< 0.9?). Please upgrade to MediaCore CE 0.9 first.') raise AssertionError('no migration table found') elif not mediacore_migrator.alembic_table_exists(): alembic_revision = mediacore_migrator.map_migrate_version() mediacore_migrator.stamp(alembic_revision) if run_migrations: mediacore_migrator.migrate_db() for migrator in plugin_manager.migrators(): migrator.migrate_db() events.Environment.database_migrated() cleanup_players_table(enabled=True) # Save everything, along with the dummy data if applicable DBSession.commit() events.Environment.database_ready() log.info('Generating appearance.css from your current settings') settings = DBSession.query(Setting.key, Setting.value) generate_appearance_css(settings, cache_dir=conf['cache_dir']) log.info('Successfully setup')