[docs]classGino(_Gino):""" Base class for GINO database. Using this class as a metadata for your database adds an additional ``get_or_404()`` method to all of your table classes. """model_base_classes=_Gino.model_base_classes+(TornadoModelMixin,)query_executor=GinoExecutoriftyping.TYPE_CHECKING:# Typehints to enable autocompletion on all Gino.Model-derived classesfrom..crudimportCRUDModelas__CRUDModelfrom..declarativeimportModelTypeas__ModelTypeclassModel(__CRUDModel,TornadoModelMixin,metaclass=__ModelType):...

[docs]classApplication(tornado.web.Application):""" Base application that provides access to the database object and defines a convenient method for initializing all the database-related stuff. """#: The database object associated with this application.#: Use :py:meth:`~.late_init()` to init this or set it manually.db=None#: If ``True``, enables ``GinoRequestHandler`` to create lazy connections.#:#: See :py:attr:`~.GinoRequestHandler.use_connection_for_request`#: for more info.use_connection_for_request=True

[docs]asyncdeflate_init(self,db:Gino,*,loop=None,options=_options):""" Initialize this application with a database object. This method does a few things to setup application for working with the database: - it enables task local storage; - creates a connection pool and binds it to the passed database object; - populates :py:attr:`~.db`. :param db: the :py:class:`gino.ext.tornado.Gino()` class instance that will be used in this application. :param loop: io loop that will be used to run heep server, either tornado's or asyncio's. :param options: a tornado's ``OptionParser()`` instance or any dictionary-like object with the database settings. Default is to use ``tornado.options.options`` global. """ifloopisNone:loop=tornado.ioloop.IOLoop.current()ifisinstance(loop,tornado.platform.asyncio.BaseAsyncIOLoop):asyncio_loop=loop.asyncio_loopelifisinstance(loop,asyncio.BaseEventLoop):asyncio_loop=loopelse:raiseRuntimeError('AsyncIOLoop is required to run GINO')_enable_inherit(asyncio_loop)self.db=dbif'dsn'inoptions:dsn=options['dsn']else:dsn=URL(drivername=options['db_driver'],host=options['db_host'],port=options['db_port'],username=options['db_user'],password=options['db_password'],database=options['db_database'],)awaitdb.set_bind(dsn,echo=options['db_echo'],min_size=options['db_pool_min_size'],max_size=options['db_pool_max_size'],max_inactive_connection_lifetime=(options['db_pool_max_inactive_conn_lifetime']),max_queries=options['db_pool_max_queries'],loop=asyncio_loop)

# noinspection PyAbstractClass

[docs]classAsyncioRequestHandler(tornado.web.RequestHandler):""" This class enables support for task locals by wrapping the ``_execute()`` method into ``asyncio.Task`` instances. """asyncdef_setup_connection(self):""" Hook for creating connection. """passasyncdef_teardown_connection(self):""" Hook for destroying connection. """passdef_execute(self,transforms,*args,**kwargs):loop=tornado.ioloop.IOLoop.current()ifnotisinstance(loop,tornado.platform.asyncio.BaseAsyncIOLoop):raiseRuntimeError('AsyncIOLoop is required to run GINO')asyncio_loop=loop.asyncio_loopreturnasyncio.ensure_future(self._do_execute(transforms,*args,**kwargs),loop=asyncio_loop)asyncdef_do_execute(self,transforms,*args,**kwargs):""" An actual asyncio-compatible implementation on the ``_execute``. This function just takes the original generator ``_execute.__wrapped__`` and manages to pass its futures to the underlying asyncio loop. It also calls ``_setup_connection`` and ``_teardown_connection`` methods and manages all errors that happen there. """self._transforms=transformstry:gen=super()._execute.__wrapped__(self,transforms,*args,**kwargs)data=Noneexc_info=Noneawaitself._setup_connection()try:whileTrue:try:ifexc_infoisNone:coro=gen.send(data)else:coro=gen.throw(*exc_info)exceptStopIteration:returnexc_info=Nonedata=None# noinspection PyBroadExceptiontry:data=awaitcoroexcept:# NOQAexc_info=sys.exc_info()finally:awaitself._teardown_connection()exceptExceptionase:# noinspection PyBroadExceptiontry:self._handle_request_exception(e)exceptException:tornado.log.app_log.exception("exception in exception handler")finally:ifself._prepared_futureisnotNone:ifnotself._prepared_future.done():self._prepared_future.set_result(None)

# noinspection PyAbstractClass

[docs]classGinoRequestHandler(AsyncioRequestHandler):""" Base class for all request handlers that use GINO. In addition to features provided by :py:class:`~.AsyncioRequestHandler`, this class manages lazy connections for each request. """__db_connection=None@propertydefuse_connection_for_request(self):""" If ``True``, a lazy connection is created for each request. That is, whenever the first query occurs, a new connection is borrowed from the application's db object. All succeeding queries made within this request will reuse that connection. The connection will be returned to the pool once the request is finished or the :py:meth:`~.release_connection()` method is called explicitly. This property is equal to :py:attr:`Application.use_connection_for_request` by default. """returnself.application.use_connection_for_request@propertydefdb(self):""" Access to the database object. This property is equal to :py:attr:`Application.db` by default. """returnself.application.dbasyncdef_setup_connection(self):ifself.use_connection_for_request:self.__db_connection=awaitself.db.acquire(lazy=True)asyncdef_teardown_connection(self):ifself.__db_connectionisnotNone:awaitself.__db_connection.release()self.__db_connection=None@propertydefdb_connection(self):""" The actual connection associated with this request or ``None`` if ``use_connection_for_request`` is ``False``. """returnself.__db_connection

[docs]asyncdefrelease_connection(self):""" Return the connection associated with this request back to the pool. """awaitself._teardown_connection()