コード例 #1
0
ファイル: test_urls.py プロジェクト: ibnesayeed/arxiv-base
    def test_relative_static_urls(self):
        """Relative static paths are enabled."""
        self.app = Flask('test')
        self.app.config['SERVER_NAME'] = 'nope.com'
        self.app.config.update({
            'SITE_HUMAN_NAME': 'The test site of testiness',
            'SITE_HUMAN_SHORT_NAME': 'Test site',
            'RELATIVE_STATIC_PATHS': True,
            'RELATIVE_STATIC_PREFIX': 'oof',
            'SITE_URL_PREFIX': '/test'
        })
        Base(self.app)

        self.app.register_blueprint(
            Blueprint('fooprint',
                      __name__,
                      url_prefix='/foo',
                      static_folder='static',
                      static_url_path='baz'))

        with self.app.app_context():
            url = url_for('base.static', filename='css/abs.css')
            self.assertTrue(
                url.startswith('http://nope.com/oof/static/base/'),
                'The static URL for base starts with the'
                ' configured prefix.')
            url = url_for('fooprint.static', filename='img/foo.jpg')
            self.assertFalse(url.startswith('http://nope.com/oof'),
                             'The blueprint static path is not affected.')
コード例 #2
0
ファイル: test_urls.py プロジェクト: ibnesayeed/arxiv-base
    def setUp(self):
        """Create a Flask app."""
        self.app = Flask('test')
        self.app.config['URLS'] = [
            ('baz', '/baz', 'baz.org'),
            ('bat', '/bat/<string:foo>', 'bat.org'),
        ]
        self.app.config['SERVER_NAME'] = 'nope.com'
        Base(self.app)

        @self.app.route('/baz_location')
        def baz_location():
            return url_for('baz')

        @self.app.route('/bat_location')
        def bat_location():
            return url_for('bat', foo=1)

        @self.app.route('/acknowledgment_location')
        def acknowledgment_location():
            return url_for('acknowledgment')

        @self.app.route('/something')
        def something():
            return 'nothing'

        self.client = self.app.test_client()
コード例 #3
0
def create_web_app() -> Flask:
    """Initialize an instance of the extractor backend service."""
    app = Flask('docs')
    app.config.from_pyfile('config.py')
    Base(app)
    app.register_blueprint(routes.blueprint)
    return app
コード例 #4
0
def create_web_app() -> Flask:
    """Initialize and configure the accounts application."""
    app = Flask('registry')
    app.config.from_pyfile('config.py')

    # app.register_blueprint(ui.blueprint)

    datastore.init_app(app)
    SessionStore.init_app(app)

    Base(app)  # Gives us access to the base UI templates and resources.
    auth.Auth(app)  # Handless sessions and authn/z.
    oauth2.init_app(app)
    app.register_blueprint(blueprint)

    middleware = [AuthMiddleware]
    if app.config['VAULT_ENABLED']:
        middleware.insert(0, vault.middleware.VaultMiddleware)
    wrap(app, middleware)
    if app.config['VAULT_ENABLED']:
        app.middlewares['VaultMiddleware'].update_secrets({})

    app.jinja_env.filters['scope_label'] = filters.scope_label

    if app.config['CREATE_DB']:
        with app.app_context():
            datastore.create_all()

    register_error_handlers(app)
    return app
コード例 #5
0
    def test_token_is_usable(self, mock_get_config):
        """Verify that :func:`.helpers.generate_token` makes usable tokens."""
        mock_get_config.return_value = {'JWT_SECRET': 'thesecret'}
        os.environ['JWT_SECRET'] = 'thesecret'
        scope = [auth.scopes.VIEW_SUBMISSION, auth.scopes.EDIT_SUBMISSION,
                 auth.scopes.CREATE_SUBMISSION]
        token = helpers.generate_token("1234", "*****@*****.**", "theuser",
                                       scope=scope)

        app = Flask('test')
        app.config['JWT_SECRET'] = 'thesecret'
        Base(app)
        auth.Auth(app)    # <- Install the Auth extension.
        wrap(app, [auth.middleware.AuthMiddleware])    # <- Install middleware.

        @app.route('/')
        @auth.decorators.scoped(auth.scopes.EDIT_SUBMISSION)
        def protected():
            return "this is protected"

        client = app.test_client()
        with app.app_context():
            response = client.get('/')
            self.assertEqual(response.status_code,
                             status.HTTP_401_UNAUTHORIZED)

            response = client.get('/', headers={'Authorization': token})
            self.assertEqual(response.status_code, status.HTTP_200_OK)
コード例 #6
0
def create_ui_web_app() -> Flask:
    """Initialize an instance of the search frontend UI web application."""
    logging.getLogger('boto').setLevel(logging.ERROR)
    logging.getLogger('boto3').setLevel(logging.ERROR)
    logging.getLogger('botocore').setLevel(logging.ERROR)

    app = Flask('search')
    app.config.from_pyfile('config.py')  # type: ignore
    app.url_map.converters['archive'] = ArchiveConverter

    index.SearchSession.init_app(app)

    Base(app)
    app.register_blueprint(ui.blueprint)

    s3.init_app(app)

    wrap(app, [request_logs.ClassicLogsMiddleware])
    # app.config['PROFILE'] = True
    # app.config['DEBUG'] = True
    # app.wsgi_app = ProfilerMiddleware(app.wsgi_app, restrictions=[100], sort_by=('cumtime', ))

    for filter_name, template_filter in filters.filters:
        app.template_filter(filter_name)(template_filter)

    return app
コード例 #7
0
def create_classic_api_web_app() -> Flask:
    """Initialize an instance of the search frontend UI web application."""
    logging.getLogger("boto").setLevel(logging.ERROR)
    logging.getLogger("boto3").setLevel(logging.ERROR)
    logging.getLogger("botocore").setLevel(logging.ERROR)

    app = Flask("search")
    app.json_encoder = ISO8601JSONEncoder
    app.config.from_pyfile("config.py")  # type: ignore

    index.SearchSession.init_app(app)

    Base(app)
    auth.Auth(app)
    app.register_blueprint(classic_api.blueprint)

    wrap(
        app,
        [request_logs.ClassicLogsMiddleware, auth.middleware.AuthMiddleware],
    )

    for error, handler in classic_api.exceptions.get_handlers():
        app.errorhandler(error)(handler)

    return app
コード例 #8
0
ファイル: factory.py プロジェクト: Tubbz-alt/arxiv-auth
def create_web_app() -> Flask:
    """Initialize and configure the accounts application."""
    app = Flask('accounts')
    app.config.from_pyfile('config.py')

    SessionStore.init_app(app)
    legacy.init_app(app)
    users.init_app(app)

    app.register_blueprint(ui.blueprint)
    Base(app)    # Gives us access to the base UI templates and resources.
    auth.Auth(app)  # Handless sessions and authn/z.
    s3.init_app(app)

    middleware = [auth.middleware.AuthMiddleware]
    if app.config['VAULT_ENABLED']:
        middleware.insert(0, vault.middleware.VaultMiddleware)
    wrap(app, middleware)
    if app.config['VAULT_ENABLED']:
        app.middlewares['VaultMiddleware'].update_secrets({})

    if app.config['CREATE_DB']:
        with app.app_context():
            legacy.create_all()
            users.create_all()

    return app
コード例 #9
0
ファイル: test_urls.py プロジェクト: ibnesayeed/arxiv-base
 def test_url_from_app_config(self):
     """url_for falls back to URLs from the application config."""
     Base(self.app)
     with self.app.app_context():
         self.assertEqual(url_for('bat', foo='yes'),
                          'https://bat.org/bat/yes')
         self.assertEqual(url_for('baz'), 'https://baz.org/baz')
コード例 #10
0
ファイル: factory.py プロジェクト: arXiv/arxiv-feed
def create_web_app() -> Flask:
    """Initialize and configure the rss application."""
    app = Flask('rss')
    app.config.from_pyfile('config.py')  # type: ignore

    Base(app)  # Gives us access to the base UI templates and resources.
    app.register_blueprint(routes.blueprint)

    return app
コード例 #11
0
ファイル: factory.py プロジェクト: pblindguy/arxiv-browse
def create_web_app() -> Flask:
    """Initialize an instance of the browse web application."""
    app = Flask('browse', static_folder='static', template_folder='templates')
    app.config.from_pyfile('config.py')

    # TODO Only needed until this route is added to arxiv-base
    if 'URLS' not in app.config:
        app.config['URLS'] = []
    app.config['URLS'].append(
        ('search_archive', '/search/<archive>', BASE_SERVER))

    models.init_app(app)

    Base(app)
    app.register_blueprint(ui.blueprint)

    ct_url_for = partial(create_ct_url, app.config.get('CLICKTHROUGH_SECRET'),
                         url_for)

    if not app.jinja_env.globals:
        app.jinja_env.globals = {}

    app.jinja_env.globals['canonical_url'] = canonical_url

    def ct_single_doi_filter(doi: str) -> str:
        return single_doi_url(ct_url_for, doi)

    def _id_to_url(id: str) -> Any:
        return url_for('browse.abstract', arxiv_id=id)

    def contextualized_id_filter(text: str) -> str:
        return do_id_to_tags(_id_to_url, text)

    def contextualized_doi_id_url_filter(text: str) -> str:
        return do_dois_id_urls_to_tags(_id_to_url, ct_url_for, text)

    def ct_doi_filter(text: str) -> str:
        return do_dois_arxiv_ids_to_tags(_id_to_url, ct_url_for, text)

    if not app.jinja_env.filters:
        app.jinja_env.filters = {}

    app.jinja_env.filters['line_feed_to_br'] = line_feed_to_br
    app.jinja_env.filters['tex_to_utf'] = tex_to_utf
    app.jinja_env.filters['entity_to_utf'] = entity_to_utf

    app.jinja_env.filters['clickthrough_url_for'] = ct_url_for
    app.jinja_env.filters['show_email_hash'] = \
        partial(generate_show_email_hash,
                secret=app.config.get('SHOW_EMAIL_SECRET'))

    app.jinja_env.filters['single_doi_url'] = ct_single_doi_filter
    app.jinja_env.filters['arxiv_id_urls'] = contextualized_id_filter
    app.jinja_env.filters['arxiv_urlize'] = contextualized_doi_id_url_filter
    app.jinja_env.filters['arxiv_id_doi_filter'] = ct_doi_filter

    return app
コード例 #12
0
def create_api_app() -> Flask:
    """Create a new API application."""
    app = Flask('funding')
    app.config.from_pyfile('config.py')
    Base(app)
    auth.Auth(app)
    app.register_blueprint(routes.api.blueprint)
    wrap(app, [auth.middleware.AuthMiddleware])
    register_error_handlers(app)
    return app
コード例 #13
0
ファイル: factory.py プロジェクト: arXiv/arxiv-marxdown
def create_web_app() -> Flask:
    """Initialize an instance of the sitemap application."""
    app = Flask('arxiv.sitemap')
    app.config.from_object(config)

    Base(app)

    app.register_blueprint(routes.blueprint)     # Provides base templates.
    s3.init_app(app)
    return app
コード例 #14
0
def create_web_app() -> Flask:
    """Initialize and configure the base application."""
    app = Flask('base_test')
    # .config is an instance of a dict subclass with some methods.
    app.config.from_object(config)  # type: ignore

    Base(app)  # Gives us access to the base UI templates and resources.
    app.register_blueprint(routes.blueprint)

    s3.init_app(app)
    return app
コード例 #15
0
def create_web_app() -> Flask:
    """Create a :class:`.Flask` app."""
    app = Flask("fourohfour")
    Base(app)

    @app.route('/healthz')
    def healthz():
        """Health check endpoint."""
        return "i'm still here", status.OK, {}

    return app
コード例 #16
0
def _create_base_app() -> Flask:
    app = Flask('zero')
    app.config.from_pyfile('config.py')
    app.json_encoder = ISO8601JSONEncoder

    baz.BazService.init_app(app)
    things.init_app(app)

    Base(app)  # Gives us access to the base UI templates and resources.
    auth.Auth(app)  # Sets up authn/z machinery.
    wrap(app, [auth.middleware.AuthMiddleware])
    return app
コード例 #17
0
def create_web_app() -> Flask:
    """Create a new :class:`.Flask` app and define the API."""
    app = Flask("fourohfour")
    Base(app)

    # Override the default error handlers to provide content negotation.
    for _, error in default_exceptions.items():
        app.errorhandler(error)(content_aware_exception_handler)

    app.route('/healthz')(healthz)
    app.route('/')(echo)
    return app
コード例 #18
0
def create_app() -> Flask:
    """Create a new API application."""
    app = Flask('preview')
    app.json_encoder = PreviewEncoder
    app.config.from_pyfile('config.py')
    Base(app)
    app.register_blueprint(routes.api)
    register_error_handlers(app)

    PreviewStore.init_app(app)
    with app.app_context():  # type: ignore
        PreviewStore.current_session().initialize()
    return app
コード例 #19
0
ファイル: factory.py プロジェクト: tana2123/arxiv-auth
def create_web_app() -> Flask:
    """Initialize and configure the accounts application."""
    app = Flask('accounts')
    app.config.from_pyfile('config.py')

    sessions.init_app(app)
    legacy.init_app(app)
    users.init_app(app)

    app.register_blueprint(ui.blueprint)
    Base(app)  # Gives us access to the base UI templates and resources.
    auth.Auth(app)  # Handless sessions and authn/z.
    wrap(app, [auth.middleware.AuthMiddleware])
    return app
コード例 #20
0
def create_app() -> Flask:
    """Create an instance of the compiler service app."""
    from . import celeryconfig
    app = Flask(__name__)
    filemanager.FileManager.init_app(app)
    store.Store.init_app(app)
    app.config.from_pyfile('config.py')
    celery_app.config_from_object(celeryconfig)

    Base(app)
    auth.Auth(app)

    app.register_blueprint(routes.blueprint)
    register_error_handlers(app)

    middleware = [auth.middleware.AuthMiddleware]

    if app.config['VAULT_ENABLED']:
        middleware.insert(0, vault.middleware.VaultMiddleware)
    wrap(app, middleware)
    if app.config['VAULT_ENABLED']:
        app.middlewares['VaultMiddleware'].update_secrets({})

    # Leaving this here for future performance tuning. - Erick
    #
    # app.config['PROFILE'] = True
    # app.config['DEBUG'] = True
    # app.wsgi_app = ProfilerMiddleware(app.wsgi_app, restrictions=[100],
    #                                   sort_by=('cumtime', ))
    #

    if app.config['WAIT_FOR_SERVICES']:
        with app.app_context():  # type: ignore
            logger.info('initialize and wait for upstream services')
            # Adding a wait here can help keep boto3 from getting stuck if
            # we are starting localstack at the same time. This can probably
            # just be 0 (default) in production.
            time.sleep(app.config['WAIT_ON_STARTUP'])
            filemanager_service = filemanager.FileManager.current_session()
            store_service = store.Store.current_session()
            store_service.initialize()
            wait_for(filemanager_service)
            if app.config['WAIT_FOR_WORKER']:
                wait_for(compiler, await_result=True)  # type: ignore

        logger.info('All upstream services are available; ready to start')

    return app
コード例 #21
0
def create_web_app() -> Flask:
    """Initialize an instance of the extractor backend service."""
    app = Flask('metadata')
    classic.init_app(app)
    app.config.from_pyfile('config.py')

    Base(app)
    auth.Auth(app)

    app.register_blueprint(routes.blueprint)
    app.errorhandler(Forbidden)(jsonify_exception)
    app.errorhandler(NotFound)(jsonify_exception)
    app.errorhandler(BadRequest)(jsonify_exception)
    app.errorhandler(Unauthorized)(jsonify_exception)

    wrap(app, [auth.middleware.AuthMiddleware])
    return app
コード例 #22
0
 def setUp(self):
     """An arXiv user is submitting a new paper."""
     self.app = Flask(__name__)
     self.app.config['EMAIL_ENABLED'] = False
     self.app.config['WAIT_FOR_SERVICES'] = False
     Base(self.app)
     init_app(self.app)
     mail.init_app(self.app)
     self.submitter = domain.User(1234,
                                  email='*****@*****.**',
                                  forename='Jane',
                                  surname='User',
                                  endorsements=['cs.DL', 'cs.IR'])
     self.unicode_submitter = domain.User(12345,
                                          email='*****@*****.**',
                                          forename='大',
                                          surname='用户',
                                          endorsements=['cs.DL', 'cs.IR'])
コード例 #23
0
def create_app() -> Flask:
    """Initialize an instance of the authenticator service."""
    app = Flask('authenticator')
    app.config.from_pyfile('config.py')

    Base(app)
    SessionStore.init_app(app)

    if app.config['VAULT_ENABLED']:
        wrap(app, [vault.middleware.VaultMiddleware])
        app.middlewares['VaultMiddleware'].update_secrets({})

    app.register_blueprint(routes.blueprint)
    app.errorhandler(NotFound)(jsonify_exception)
    app.errorhandler(BadRequest)(jsonify_exception)
    app.errorhandler(Unauthorized)(jsonify_exception)
    app.errorhandler(Forbidden)(jsonify_exception)
    return app
コード例 #24
0
ファイル: test_urls.py プロジェクト: ibnesayeed/arxiv-base
    def test_static_urls(self):
        """We have vanilla Flask app with a blueprint."""
        self.app = Flask('test')
        self.app.config['SERVER_NAME'] = 'nope.com'
        Base(self.app)

        self.app.register_blueprint(
            Blueprint('fooprint',
                      __name__,
                      url_prefix='/foo',
                      static_folder='static',
                      static_url_path='baz'))

        with self.app.app_context():
            url = url_for('base.static', filename='css/abs.css')
            self.assertTrue(url.startswith('http://nope.com/static/base/'))
            url = url_for('fooprint.static', filename='img/foo.jpg')
            self.assertTrue(url.startswith('http://nope.com/foo/static/test/'))
コード例 #25
0
def create_ui_web_app() -> Flask:
    """Initialize an instance of the search frontend UI web application."""
    logging.getLogger('boto').setLevel(logging.ERROR)
    logging.getLogger('boto3').setLevel(logging.ERROR)
    logging.getLogger('botocore').setLevel(logging.ERROR)

    app = Flask('search')
    app.config.from_pyfile('config.py')

    index.init_app(app)

    Base(app)
    app.register_blueprint(ui.blueprint)

    s3.init_app(app)

    wrap(app, [request_logs.ClassicLogsMiddleware])

    return app
コード例 #26
0
def create_app() -> Flask:
    """Create a new agent application."""
    app = Flask(__name__)
    app.config.from_object(config)
    app.config.add_hook('SUBMISSION_AGENT_DATABASE_URI', update_binds)

    Base(app)

    # Register logging and secrets middleware.
    middleware = [request_logs.ClassicLogsMiddleware]
    if app.config['VAULT_ENABLED']:
        middleware.insert(0, vault.middleware.VaultMiddleware)
    wrap(app, middleware)

    # Make sure that we have all of the secrets that we need to run.
    if app.config['VAULT_ENABLED']:
        app.middlewares['VaultMiddleware'].update_secrets({})

    # Initialize services.
    database.init_app(app)
    mail.init_app(app)
    Classifier.init_app(app)
    Compiler.init_app(app)
    PlainTextService.init_app(app)
    init_app(app)

    if app.config['WAIT_FOR_SERVICES']:
        time.sleep(app.config['WAIT_ON_STARTUP'])
        with app.app_context():
            wait_for(database)
            wait_for(Classifier.current_session(),
                     timeout=app.config['CLASSIFIER_STATUS_TIMEOUT'])
            wait_for(Compiler.current_session(),
                     timeout=app.config['COMPILER_STATUS_TIMEOUT'])
            wait_for(PlainTextService.current_session(),
                     timeout=app.config['PLAINTEXT_STATUS_TIMEOUT'])
            # FILEMANAGER_STATUS_TIMEOUT
        logger.info('All upstream services are available; ready to start')

    with app.app_context():
        if not database.tables_exist():
            database.create_all()
    return app
コード例 #27
0
ファイル: factory.py プロジェクト: tana2123/arxiv-auth
def create_web_app() -> Flask:
    """Initialize and configure the accounts application."""
    app = Flask('registry')
    app.config.from_pyfile('config.py')

    # app.register_blueprint(ui.blueprint)

    datastore.init_app(app)
    sessions.init_app(app)

    Base(app)  # Gives us access to the base UI templates and resources.
    auth.Auth(app)  # Handless sessions and authn/z.
    oauth2.init_app(app)
    app.register_blueprint(blueprint)
    wrap(app, [auth.middleware.AuthMiddleware])

    app.jinja_env.filters['scope_label'] = filters.scope_label

    datastore.create_all()
    return app
コード例 #28
0
def create_web_app(for_worker: bool = False) -> Flask:
    """Initialize an instance of the web application."""
    app = Flask('fulltext')
    app.config.from_pyfile('config.py')
    app.url_map.converters['source'] = SubmissionSourceConverter

    if app.config['LOGLEVEL'] < 40:
        # Make sure that boto doesn't spam the logs when we're in debug mode.
        pylogging.getLogger('boto').setLevel(pylogging.ERROR)
        pylogging.getLogger('boto3').setLevel(pylogging.ERROR)
        pylogging.getLogger('botocore').setLevel(pylogging.ERROR)

    Base(app)
    Auth(app)
    app.register_blueprint(routes.blueprint)
    store.Storage.current_session().init_app(app)
    legacy.CanonicalPDF.init_app(app)
    preview.PreviewService.init_app(app)

    middleware = [auth.middleware.AuthMiddleware]
    if app.config['VAULT_ENABLED']:
        middleware.insert(0, vault.middleware.VaultMiddleware)
    wrap(app, middleware)
    if app.config['VAULT_ENABLED']:
        app.middlewares['VaultMiddleware'].update_secrets({})

    if app.config['WAIT_FOR_SERVICES']:
        time.sleep(app.config['WAIT_ON_STARTUP'])
        with app.app_context():
            wait_for(store.Storage.current_session())
            wait_for(legacy.CanonicalPDF.current_session())
            wait_for(preview.PreviewService.current_session())
            if for_worker:
                wait_for(extractor.do_extraction)
            else:
                wait_for(extract, await_result=True)  # type: ignore
        logger.info('All upstream services are available; ready to start')

    register_error_handlers(app)
    app.celery_app = extract.get_or_create_worker_app(app)
    return app
コード例 #29
0
ファイル: factory.py プロジェクト: arXiv/arxiv-marxdown
def create_web_app(build_path: Optional[str] = None,
                   with_search: Optional[bool] = None,
                   extra_config: Optional[dict] = None,
                   instance_path: Optional[str] = None,
                   static_url_path: Optional[str] = None) -> Flask:
    """Initialize an instance of the static pages application."""
    app = Flask('arxiv.marxdown',
                static_url_path=static_url_path,
                instance_path=instance_path,
                instance_relative_config=True)

    app.config.from_object(config)  # Default configuration.

    # If available, use an instance config from the instance folder. See
    # https://flask.palletsprojects.com/en/1.1.x/config/#instance-folders.
    # Config params here will override defaults.
    app.config.from_pyfile('application.cfg', silent=True)

    build_path = build_path or app.config.get('BUILD_PATH', "./")
    with_search = with_search or app.config.get('SITE_SEARCH_ENABLED', True)

    if extra_config is not None:
        app.config.update(extra_config)

    Base(app)

    with app.app_context():  # Need the app context for the config to stick.
        # Provides base templates.
        app.register_blueprint(routes.get_docs_blueprint(app))

        # We build the blueprint on the fly, so that we get dynamic routing
        # to content pages.
        app.register_blueprint(
            routes.get_blueprint(build_path, with_search=with_search))

    app.jinja_env.filters['format_datetime'] = format_datetime  # pylint: disable=no-member
    app.jinja_env.filters['simpledate'] = simpledate  # pylint: disable=no-member
    app.jinja_env.filters['pretty_path'] = pretty_path  # pylint: disable=no-member

    s3.init_app(app)
    return app
コード例 #30
0
ファイル: factory.py プロジェクト: arXiv/arxiv-submission-ui
def create_ui_web_app() -> Flask:
    """Initialize an instance of the search frontend UI web application."""
    app = Flask('submit', static_folder='static', template_folder='templates')
    app.url_map.strict_slashes = False
    app.config.from_pyfile('config.py')

    Base(app)
    auth.Auth(app)
    app.register_blueprint(ui.ui)

    middleware = [
        request_logs.ClassicLogsMiddleware, auth.middleware.AuthMiddleware
    ]
    if app.config['VAULT_ENABLED']:
        middleware.insert(0, vault.middleware.VaultMiddleware)
    wrap(app, middleware)

    # Make sure that we have all of the secrets that we need to run.
    if app.config['VAULT_ENABLED']:
        app.middlewares['VaultMiddleware'].update_secrets({})

    for filter_name, filter_func in filters.get_filters():
        app.jinja_env.filters[filter_name] = filter_func

    # Initialize services.
    init_app(app)
    Compiler.init_app(app)
    FileManager.init_app(app)

    if app.config['WAIT_FOR_SERVICES']:
        time.sleep(app.config['WAIT_ON_STARTUP'])
        with app.app_context():
            wait_for(FileManager.current_session(),
                     timeout=app.config['FILEMANAGER_STATUS_TIMEOUT'])
            wait_for(Compiler.current_session(),
                     timeout=app.config['COMPILER_STATUS_TIMEOUT'])
        logger.info('All upstream services are available; ready to start')

    return app