Пример #1
0
def create_app(**config):
    """
    Create the application and return it to the user
    :return: flask.Flask application
    """

    if config:
        app = ADSFlask(__name__, local_config=config)
    else:
        app = ADSFlask(__name__)

    app.url_map.strict_slashes = False

    # Add end points
    api = Api(app)
    api.add_resource(IndexView, '/tugboat/index')
    api.add_resource(ClassicSearchRedirectView,
                     '/tugboat/classicSearchRedirect')
    api.add_resource(BumblebeeView, '/tugboat/redirect')
    api.add_resource(SimpleClassicView, '/tugboat/ads')
    api.add_resource(ComplexClassicView, '/tugboat/adsabs')
    api.add_resource(ComplexClassicArXivView, '/tugboat/arxiv')
    api.add_resource(ComplexClassicPhysicsView, '/tugboat/physics')

    Discoverer(app)

    return app
Пример #2
0
def create_app(**config):

    app = ADSFlask(__name__, static_folder=None, local_config=config or {})

    app.url_map.strict_slashes = False

    ## pysqlite driver breaks transactions, we have to apply some hacks as per
    ## http://docs.sqlalchemy.org/en/rel_0_9/dialects/sqlite.html#pysqlite-serializable
    if 'sqlite' in app.config.get('SQLALCHEMY_DATABASE_URI', None):
        from sqlalchemy import event
        engine = app.db.engine

        @event.listens_for(engine, "connect")
        def do_connect(dbapi_connection, connection_record):
            # disable pysqlite's emitting of the BEGIN statement entirely.
            # also stops it from emitting COMMIT before any DDL.
            dbapi_connection.isolation_level = None

        @event.listens_for(engine, "begin")
        def do_begin(conn):
            # emit our own BEGIN
            conn.execute("BEGIN")

    app.register_blueprint(bp)

    discoverer = Discoverer(app)

    class JsonResponse(Response):
        default_mimetype = 'application/json'

    app.response_class = JsonResponse

    return app
Пример #3
0
 def __init__(self, app_name, *args, **kwargs):
     """
     :param: app_name - string, name of the application (can be anything)
     :keyword: local_config - dict, configuration that should be applied
         over the default config (that is loaded from config.py and local_config.py)
     """
     ADSFlask.__init__(self, app_name, *args, **kwargs)
Пример #4
0
    def __init__(self, *args, **kwargs):
        ADSFlask.__init__(self, *args, **kwargs)

        # HTTP client is provided by requests module; it handles connection pooling
        # here we just set some headers we always want to use while sending a request
        self.client.headers.update({
            'Authorization':
            'Bearer {}'.format(self.config.get("API_TOKEN", ''))
        })
Пример #5
0
def create_app(**config):
    """
    Create the application and return it to the user
    :return: application
    """

    if config:
        app = ADSFlask(__name__, static_folder=None, local_config=config)
    else:
        app = ADSFlask(__name__, static_folder=None)
    app.url_map.strict_slashes = False

    load_s3(app)

    # Register extensions
    watchman = Watchman(app, version=dict(scopes=['']))
    api = Api(app)
    Discoverer(app)

    # Add the end resource end points
    api.add_resource(AuthenticateUserClassic, '/auth/classic', methods=['POST'])
    api.add_resource(AuthenticateUserTwoPointOh, '/auth/twopointoh', methods=['POST'])

    api.add_resource(
        ClassicLibraries,
        '/libraries/classic/<int:uid>',
        methods=['GET']
    )
    api.add_resource(
        TwoPointOhLibraries,
        '/libraries/twopointoh/<int:uid>',
        methods=['GET']
    )

    api.add_resource(
        ExportTwoPointOhLibraries,
        '/export/twopointoh/<export>',
        methods=['GET']
    )

    api.add_resource(
        ClassicMyADS,
        '/myads/classic/<int:uid>',
        methods=['GET']
    )

    api.add_resource(ClassicUser, '/user', methods=['GET'])
    api.add_resource(AllowedMirrors, '/mirrors', methods=['GET'])

    return app
Пример #6
0
 def test_config(self):
     app = ADSFlask(u'test',
                    local_config={
                        u'FOO': [u'bar', {}],
                        u'SQLALCHEMY_DATABASE_URI': u'sqlite:///',
                    })
     self.assertEqual(app._config[u'FOO'], [u'bar', {}])
     self.assertEqual(app.config[u'FOO'], [u'bar', {}])
     self.assertTrue(app.db)
Пример #7
0
def create_app(**config):

    opath = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
    if opath not in sys.path:
        sys.path.insert(0, opath)

    if config:
        app = ADSFlask(__name__, static_folder=None, local_config=config)
    else:
        app = ADSFlask(__name__, static_folder=None)

    app.url_map.strict_slashes = False

    ## pysqlite driver breaks transactions, we have to apply some hacks as per
    ## http://docs.sqlalchemy.org/en/rel_0_9/dialects/sqlite.html#pysqlite-serializable

    if 'sqlite' in app.config.get('SQLALCHEMY_DATABASE_URI', None):
        from sqlalchemy import event
        engine = app.db.engine

        @event.listens_for(engine, "connect")
        def do_connect(dbapi_connection, connection_record):
            # disable pysqlite's emitting of the BEGIN statement entirely.
            # also stops it from emitting COMMIT before any DDL.
            dbapi_connection.isolation_level = None

        @event.listens_for(engine, "begin")
        def do_begin(conn):
            # emit our own BEGIN
            conn.execute("BEGIN")

    # Note about imports being here rather than at the top level
    # I want to enclose the import into the scope of the create_app()
    # and not advertise any of the views; and yes, i'm importing
    # everything from inside views (everything in __all__)
    from . import views
    for o in inspect.getmembers(views,
                                predicate=lambda x: inspect.ismodule(x)):
        for blueprint in inspect.getmembers(
                o[1], predicate=lambda x: isinstance(x, Blueprint)):
            app.register_blueprint(blueprint[1])

    discoverer = Discoverer(app)

    class JsonResponse(Response):
        default_mimetype = 'application/json'

    app.response_class = JsonResponse
    """
    @app.after_request
    def after_request_func(response):
        # by default (almost all our) responses are
        # mimetype application/json
        if 'Content-Type' not in response.headers:
            response.headers['Content-Type'] = 'application/json'
        return response
    """

    return app
Пример #8
0
def create_app(**config):

    opath = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
    if opath not in sys.path:
        sys.path.insert(0, opath)

    if config:
        app = ADSFlask(__name__, static_folder=None, local_config=config)
    else:
        app = ADSFlask(__name__, static_folder=None)

    app.url_map.strict_slashes = False

    ## pysqlite driver breaks transactions, we have to apply some hacks as per
    ## http://docs.sqlalchemy.org/en/rel_0_9/dialects/sqlite.html#pysqlite-serializable

    if 'sqlite' in app.config.get('SQLALCHEMY_DATABASE_URI', None):
        from sqlalchemy import event
        engine = app.db.engine

        @event.listens_for(engine, "connect")
        def do_connect(dbapi_connection, connection_record):
            # disable pysqlite's emitting of the BEGIN statement entirely.
            # also stops it from emitting COMMIT before any DDL.
            dbapi_connection.isolation_level = None

        @event.listens_for(engine, "begin")
        def do_begin(conn):
            # emit our own BEGIN
            conn.execute("BEGIN")


    # Note about imports being here rather than at the top level
    # I want to enclose the import into the scope of the create_app()
    # and not advertise any of the views; and yes, i'm importing
    # everything from inside views (everything in __all__)
    from . import views
    for o in inspect.getmembers(views, predicate=lambda x: inspect.ismodule(x)):
        for blueprint in inspect.getmembers(o[1], predicate=lambda x: isinstance(x, Blueprint)):
            app.register_blueprint(blueprint[1])

    discoverer = Discoverer(app)

    return app
Пример #9
0
def create_app(**config):
    """
    Create the application and return it to the user
    :return: flask.Flask application
    """

    if config:
        app = ADSFlask(__name__, static_folder=None, local_config=config)
    else:
        app = ADSFlask(__name__, static_folder=None)

    app.url_map.strict_slashes = False

    api = Api(app)
    api.add_resource(Graphics, '/<string:bibcode>')

    Discoverer(app)

    return app
Пример #10
0
 def create_app(self):
     '''Start the wsgi application'''
     local_config = {
         'SQLALCHEMY_DATABASE_URI': self.postgresql_url,
         'SQLALCHEMY_ECHO': False,
         'TESTING': True,
         'PROPAGATE_EXCEPTIONS': True,
         'TRAP_BAD_REQUEST_ERRORS': True
     }
     app = ADSFlask(__name__, static_folder=None, local_config=local_config)
     return app
Пример #11
0
def create_app(**config):
    opath = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
    if opath not in sys.path:
        sys.path.insert(0, opath)

    if config:
        app = ADSFlask(__name__, static_folder=None, local_config=config)
    else:
        app = ADSFlask(__name__, static_folder=None)

    app.url_map.strict_slashes = False

    if app.config['MINIFY']:
        minify(app=app,
               html=True,
               js=True,
               cssless=True,
               cache=False,
               fail_safe=True,
               bypass=[])

    return app
Пример #12
0
def create_app(**config):
    opath = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
    if opath not in sys.path:
        sys.path.insert(0, opath)

    if config:
        app = ADSFlask(__name__, static_folder=None, local_config=config)
    else:
        app = ADSFlask(__name__, static_folder=None)

    app.url_map.strict_slashes = False

    if app.config['MINIFY']:
        minify(app=app, html=True, js=True, cssless=True, cache=False, fail_safe=True, bypass=[])
    
    Limiter(app, key_func=get_remote_address)
    FlaskRedisPool(app)
    
    if app.config['ENVIRONMENT'] == "localhost":
        app.debug = True
    
    return app
Пример #13
0
def create_app(**config):
    """Application factory"""

    app = ADSFlask(__name__, static_folder=None, local_config=config or {})

    app.url_map.strict_slashes = False

    api = Api(app)

    api.add_resource(WordCloud, '/word-cloud')
    api.add_resource(AuthorNetwork, '/author-network')
    api.add_resource(PaperNetwork, '/paper-network')

    discoverer = Discoverer(app)

    return app
Пример #14
0
def create_app():
    """
    Create the application and return it to the user
    :return: flask.Flask application
    """

    app = ADSFlask(__name__, static_folder=None)
    app.url_map.strict_slashes = False

    api = Api(app)
    api.add_resource(ObjectSearch, '/', '/<string:objects>',
                     '/<string:objects>/<string:source>')
    api.add_resource(QuerySearch, '/query')
    api.add_resource(ClassicObjectSearch, '/nedsrv')

    discoverer = Discoverer(app)

    return app
Пример #15
0
def create_app(**config):
    """
    Create the application and return it to the user
    :return: flask.Flask application
    """

    if config:
        app = ADSFlask(__name__, static_folder=None, local_config=config)
    else:
        app = ADSFlask(__name__, static_folder=None)

    app.url_map.strict_slashes = False

    Discoverer(app)

    app.register_blueprint(bp)
    return app
Пример #16
0
 def __init__(self, *args, **kwargs):
     ADSFlask.__init__(self, *args, **kwargs)
     
     # HTTP client is provided by requests module; it handles connection pooling
     # here we just set some headers we always want to use while sending a request
     self.client.headers.update({'Authorization': 'Bearer {}'.format(self.config.get("API_TOKEN", ''))})
Пример #17
0
def create_app(**config):
    """
    Application factory
    :return configured flask.Flask application instance
    """
    if config:
        app = ADSFlask(__name__, static_folder=None, local_config=config)
    else:
        app = ADSFlask(__name__, static_folder=None)

    app.url_map.strict_slashes = False

    ## pysqlite driver breaks transactions, we have to apply some hacks as per
    ## http://docs.sqlalchemy.org/en/rel_0_9/dialects/sqlite.html#pysqlite-serializable

    if 'sqlite' in app.config.get('SQLALCHEMY_DATABASE_URI', None):
        from sqlalchemy import event
        engine = app.db.engine

        @event.listens_for(engine, "connect")
        def do_connect(dbapi_connection, connection_record):
            # disable pysqlite's emitting of the BEGIN statement entirely.
            # also stops it from emitting COMMIT before any DDL.
            dbapi_connection.isolation_level = None

        @event.listens_for(engine, "begin")
        def do_begin(conn):
            # emit our own BEGIN
            conn.execute("BEGIN")

    api = Api(app)

    @api.representation('application/json')
    def json(data, code, headers):
        """
        Since we force SOLR to always return JSON, it is faster to
        return JSON as text string directly, without parsing and serializing
        it multiple times
        """
        if not isinstance(data, basestring):
            resp = jsonify(data)
            resp.status_code = code
        else:
            resp = make_response(data, code)
        resp.headers['Content-Type'] = 'application/json'
        resp.headers['Server'] = 'Solr Microservice {v}'.format(
            v=app.config.get('SOLR_SERVICE_VERSION'))
        if code == 200:
            resp.headers['Cache-Control'] = app.config.get(
                'SOLR_CACHE_CONTROL', "public, max-age=600")
        if 'Set-Cookie' in headers:
            resp.headers['Set-Cookie'] = headers['Set-Cookie']
        return resp

    api.add_resource(StatusView, '/status')
    api.add_resource(Tvrh, '/tvrh')
    api.add_resource(Search, '/query')
    api.add_resource(Qtree, '/qtree')
    api.add_resource(BigQuery, '/bigquery')

    Discoverer(app)
    return app
Пример #18
0
 def create_app(self):
     '''Start the wsgi application'''
     local_config = {}
     app = ADSFlask(__name__, static_folder=None, local_config=local_config)
     return app
Пример #19
0
def create_app(app_name=None, instance_path=None, static_path=None,
               static_folder=None, **config):
    """Returns a :class:`Flask` application instance configured with common
    functionality for the AdsWS platform.

    :param app_name: application package name
    :param instance_path: application package path
    :param static_path: flask.Flask static_path kwarg
    :param static_folder: flask.Flask static_folder kwarg
    :param config: a dictionary of settings to override
    """
    # Flask application name
    app_name = app_name or '.'.join(__name__.split('.')[0:-1])

    # Force instance folder to always be located one level above adsws
    instance_path = instance_path or os.path.realpath(os.path.join(
        os.path.dirname(__file__), '../instance'
    ))

    # Create instance path
    try:
        if not os.path.exists(instance_path):
            os.makedirs(instance_path)
    except:
        pass

    app = ADSFlask(
        app_name,
        instance_path=instance_path,
        instance_relative_config=False,
        static_path=static_path,
        static_folder=static_folder,
        local_config=config or {}
    )

    # Handle both URLs with and without trailing slashes by Flask.
    app.url_map.strict_slashes = False

    load_config(app, config)

    # Ensure SECRET_KEY has a value in the application configuration
    register_secret_key(app)

    # ====================
    # Application assembly
    # ====================
    # Initialize application registry, used for discovery and loading of
    # configuration, extensions and Invenio packages
    Registry(app=app)

    app.extensions['registry'].update(
        # Register packages listed in config
        packages=PackageRegistry(app))

    app.extensions['registry'].update(
        # Register extensions listed in config
        extensions=ExtensionRegistry(app),
        # Register blueprints
        blueprints=BlueprintAutoDiscoveryRegistry(app=app),
    )

    # Extend application config with configuration from packages (app config
    # takes precedence)
    ConfigurationRegistry(app)

    configure_a_more_verbose_log_exception(app)

    app.wsgi_app = HTTPMethodOverrideMiddleware(app.wsgi_app)

    app.before_request(set_translations)
    app.before_request(make_session_permanent)

    if app.config.get('PRODUCTION', False):
        app.wsgi_app = ProxyFix(
            app.wsgi_app,
            num_proxies=app.config.get('NUM_PROXIES', 2)
        )

    if app.config.get('HTTPS_ONLY', False):
        # Contains the x-forwarded-proto in the criteria already
        # only works if app.debug=False
        # permanent=True responds with 302 instead of 301
        SSLify(app, permanent=True)

    # Register custom error handlers
    if not app.config.get('DEBUG'):
        app.errorhandler(404)(on_404)
        app.errorhandler(401)(on_401)
        app.errorhandler(429)(on_429)
        app.errorhandler(405)(on_405)

    @oauth2.after_request
    def set_adsws_uid_header(valid, oauth):
        """
        If the user is authenticated, inject the header "X-adsws-uid" into
        the incoming request header
        """
        if current_user.is_authenticated():
            h = Headers(request.headers.items())
            h.add_header("X-Adsws-Uid", current_user.id)
            if current_user.ratelimit_level is not None:
                h.add_header(
                    "X-Adsws-Ratelimit-Level",
                    current_user.ratelimit_level
                )
            request.headers = h
        return valid, oauth
    return app
Пример #20
0
def create_app(app_name=None,
               instance_path=None,
               static_path=None,
               static_folder=None,
               **config):
    """Returns a :class:`Flask` application instance configured with common
    functionality for the AdsWS platform.

    :param app_name: application package name
    :param instance_path: application package path
    :param static_path: flask.Flask static_path kwarg
    :param static_folder: flask.Flask static_folder kwarg
    :param config: a dictionary of settings to override
    """
    # Flask application name
    app_name = app_name or '.'.join(__name__.split('.')[0:-1])

    # Force instance folder to always be located one level above adsws
    instance_path = instance_path or os.path.realpath(
        os.path.join(os.path.dirname(__file__), '../instance'))

    # Create instance path
    try:
        if not os.path.exists(instance_path):
            os.makedirs(instance_path)
    except:
        pass

    app = ADSFlask(app_name,
                   instance_path=instance_path,
                   instance_relative_config=False,
                   static_path=static_path,
                   static_folder=static_folder,
                   local_config=config or {})

    # Handle both URLs with and without trailing slashes by Flask.
    app.url_map.strict_slashes = False

    load_config(app, config)

    # Ensure SECRET_KEY has a value in the application configuration
    register_secret_key(app)

    # ====================
    # Application assembly
    # ====================
    # Initialize application registry, used for discovery and loading of
    # configuration, extensions and Invenio packages
    Registry(app=app)

    app.extensions['registry'].update(
        # Register packages listed in config
        packages=PackageRegistry(app))

    app.extensions['registry'].update(
        # Register extensions listed in config
        extensions=ExtensionRegistry(app),
        # Register blueprints
        blueprints=BlueprintAutoDiscoveryRegistry(app=app),
    )

    # Extend application config with configuration from packages (app config
    # takes precedence)
    ConfigurationRegistry(app)

    configure_a_more_verbose_log_exception(app)

    app.wsgi_app = HTTPMethodOverrideMiddleware(app.wsgi_app)

    app.before_request(set_translations)
    app.before_request(make_session_permanent)

    if app.config.get('PRODUCTION', False):
        app.wsgi_app = ProxyFix(app.wsgi_app,
                                num_proxies=app.config.get('NUM_PROXIES', 2))

    if app.config.get('HTTPS_ONLY', False):
        # Contains the x-forwarded-proto in the criteria already
        # only works if app.debug=False
        # permanent=True responds with 302 instead of 301
        SSLify(app, permanent=True)

    # Register custom error handlers
    if not app.config.get('DEBUG'):
        app.errorhandler(404)(on_404)
        app.errorhandler(401)(on_401)
        app.errorhandler(429)(on_429)
        app.errorhandler(405)(on_405)

    @oauth2.after_request
    def set_adsws_uid_header(valid, oauth):
        """
        If the user is authenticated, inject the header "X-adsws-uid" into
        the incoming request header
        """
        if current_user.is_authenticated():
            h = Headers(request.headers.items())
            h.add_header("X-Adsws-Uid", current_user.id)
            if current_user.ratelimit_level is not None:
                h.add_header("X-Adsws-Ratelimit-Level",
                             current_user.ratelimit_level)
            request.headers = h
        return valid, oauth

    return app
Пример #21
0
def create_app(app_name=None,
               instance_path=None,
               static_path=None,
               static_folder=None,
               **config):
    """Returns a :class:`Flask` application instance configured with common
    functionality for the AdsWS platform.

    :param app_name: application package name
    :param instance_path: application package path
    :param static_path: flask.Flask static_path kwarg
    :param static_folder: flask.Flask static_folder kwarg
    :param config: a dictionary of settings to override
    """
    # Flask application name
    app_name = app_name or '.'.join(__name__.split('.')[0:-1])

    # Force instance folder to always be located one level above adsws
    instance_path = instance_path or os.path.realpath(
        os.path.join(os.path.dirname(__file__), '../instance'))

    # Create instance path
    try:
        if not os.path.exists(instance_path):
            os.makedirs(instance_path)
    except:
        pass

    app = ADSFlask(app_name,
                   instance_path=instance_path,
                   instance_relative_config=False,
                   static_path=static_path,
                   static_folder=static_folder,
                   local_config=config or {})

    # Handle both URLs with and without trailing slashes by Flask.
    app.url_map.strict_slashes = False

    load_config(app, config)

    # Ensure SECRET_KEY has a value in the application configuration
    register_secret_key(app)

    # ====================
    # Application assembly
    # ====================
    # Initialize application registry, used for discovery and loading of
    # configuration, extensions and Invenio packages
    Registry(app=app)

    app.extensions['registry'].update(
        # Register packages listed in config
        packages=PackageRegistry(app))

    app.extensions['registry'].update(
        # Register extensions listed in config
        extensions=ExtensionRegistry(app),
        # Register blueprints
        blueprints=BlueprintAutoDiscoveryRegistry(app=app),
    )

    # Extend application config with configuration from packages (app config
    # takes precedence)
    ConfigurationRegistry(app)

    configure_a_more_verbose_log_exception(app)

    app.wsgi_app = HTTPMethodOverrideMiddleware(app.wsgi_app)

    app.before_request(set_translations)
    app.before_request(make_session_permanent)
    app.before_request(cache_data_stream)

    if app.config.get('PRODUCTION', False):
        app.wsgi_app = ProxyFix(app.wsgi_app,
                                num_proxies=app.config.get('NUM_PROXIES', 2))

    if app.config.get('HTTPS_ONLY', False):
        # Contains the x-forwarded-proto in the criteria already
        # only works if app.debug=False
        # permanent=True responds with 302 instead of 301
        SSLify(app, permanent=True)

    # Register custom error handlers
    if not app.config.get('DEBUG'):
        app.errorhandler(404)(on_404)
        app.errorhandler(401)(on_401)
        app.errorhandler(429)(on_429)
        app.errorhandler(405)(on_405)

    @oauth2.after_request
    def set_adsws_uid_header(valid, oauth):
        """
        If the user is authenticated, inject the header "X-adsws-uid" into
        the incoming request header
        """
        h = Headers(request.headers.items())

        if current_user.is_authenticated():
            h.add_header("X-Adsws-Uid", current_user.id)

        if valid:
            level = oauth.client.ratelimit
            if level is None:
                level = 1.0
            h.add_header("X-Adsws-Ratelimit-Level", level)
        else:
            h.add_header("X-Adsws-Ratelimit-Level", 0.0)

        request.headers = h
        return valid, oauth

    @app.teardown_request
    def teardown_request(exception=None):
        """This function will close active transaction, if there is one
        but only if the session is not dirty - we don't want to do any
        magic (instead of a developer)
        
        use expire_on_commit=False doesn't have the same effect
        http://docs.sqlalchemy.org/en/latest/orm/session_api.html#sqlalchemy.orm.session.Session.commit
        
        The problems we are facing is that a new transaction gets opened
        when session is committed; consequent access to the ORM objects
        opens a new transaction (which never gets closed and is rolled back)
        """
        a = current_app
        if 'sqlalchemy' in a.extensions:  # could use self.db but let's be very careful
            sa = a.extensions['sqlalchemy']
            if hasattr(sa, 'db') and hasattr(
                    sa.db, 'session') and sa.db.session.is_active:
                if bool(sa.db.session.dirty):
                    sa.db.session.close()  # db server will do rollback
                else:
                    sa.db.session.commit()  # normal situation

    return app
Пример #22
0
def create_app(app_name=None, instance_path=None, static_path=None,
               static_folder=None, **config):
    """Returns a :class:`Flask` application instance configured with common
    functionality for the AdsWS platform.

    :param app_name: application package name
    :param instance_path: application package path
    :param static_path: flask.Flask static_path kwarg
    :param static_folder: flask.Flask static_folder kwarg
    :param config: a dictionary of settings to override
    """
    # Flask application name
    app_name = app_name or '.'.join(__name__.split('.')[0:-1])

    # Force instance folder to always be located one level above adsws
    instance_path = instance_path or os.path.realpath(os.path.join(
        os.path.dirname(__file__), '../instance'
    ))

    # Create instance path
    try:
        if not os.path.exists(instance_path):
            os.makedirs(instance_path)
    except:
        pass

    app = ADSFlask(
        app_name,
        instance_path=instance_path,
        instance_relative_config=False,
        static_path=static_path,
        static_folder=static_folder,
        local_config=config or {}
    )

    # Handle both URLs with and without trailing slashes by Flask.
    app.url_map.strict_slashes = False

    load_config(app, config)

    # Ensure SECRET_KEY has a value in the application configuration
    register_secret_key(app)

    # ====================
    # Application assembly
    # ====================
    # Initialize application registry, used for discovery and loading of
    # configuration, extensions and Invenio packages
    Registry(app=app)

    app.extensions['registry'].update(
        # Register packages listed in config
        packages=PackageRegistry(app))

    app.extensions['registry'].update(
        # Register extensions listed in config
        extensions=ExtensionRegistry(app),
        # Register blueprints
        blueprints=BlueprintAutoDiscoveryRegistry(app=app),
    )

    # Extend application config with configuration from packages (app config
    # takes precedence)
    ConfigurationRegistry(app)

    configure_a_more_verbose_log_exception(app)

    app.wsgi_app = HTTPMethodOverrideMiddleware(app.wsgi_app)

    app.before_request(set_translations)
    app.before_request(make_session_permanent)
    app.before_request(cache_data_stream)

    if app.config.get('PRODUCTION', False):
        app.wsgi_app = ProxyFix(
            app.wsgi_app,
            num_proxies=app.config.get('NUM_PROXIES', 2)
        )

    if app.config.get('HTTPS_ONLY', False):
        # Contains the x-forwarded-proto in the criteria already
        # only works if app.debug=False
        # permanent=True responds with 302 instead of 301
        SSLify(app, permanent=True)

    # Register custom error handlers
    if not app.config.get('DEBUG'):
        app.errorhandler(404)(on_404)
        app.errorhandler(401)(on_401)
        app.errorhandler(429)(on_429)
        app.errorhandler(405)(on_405)

    @oauth2.after_request
    def set_adsws_uid_header(valid, oauth):
        """
        If the user is authenticated, inject the header "X-adsws-uid" into
        the incoming request header
        """
        h = Headers(request.headers.items())
        
        if current_user.is_authenticated():
            h.add_header("X-Adsws-Uid", current_user.id)
            
        if valid:    
            level = oauth.client.ratelimit
            if level is None:
                level = 1.0
            h.add_header("X-Adsws-Ratelimit-Level", level)
        else:
            h.add_header("X-Adsws-Ratelimit-Level", 0.0)
        
        request.headers = h
        return valid, oauth
    
    @app.teardown_request
    def teardown_request(exception=None):
        """This function will close active transaction, if there is one
        but only if the session is not dirty - we don't want to do any
        magic (instead of a developer)
        
        use expire_on_commit=False doesn't have the same effect
        http://docs.sqlalchemy.org/en/latest/orm/session_api.html#sqlalchemy.orm.session.Session.commit
        
        The problems we are facing is that a new transaction gets opened
        when session is committed; consequent access to the ORM objects
        opens a new transaction (which never gets closed and is rolled back)
        """
        a = current_app
        if 'sqlalchemy' in a.extensions: # could use self.db but let's be very careful
            sa = a.extensions['sqlalchemy']
            if hasattr(sa, 'db') and hasattr(sa.db, 'session') and sa.db.session.is_active:
                if bool(sa.db.session.dirty):
                    sa.db.session.close() # db server will do rollback
                else:
                    sa.db.session.commit() # normal situation
                
    return app