ploneasgi.zopeapp#

Starting and stopping Zope without PasteDeploy.

Everything in this module imports Zope lazily, so the rest of ploneasgi remains importable — and testable — without Plone installed.

Named zopeapp rather than zope on purpose: a top-level module called zope inside this package would be a confusing neighbour to the zope namespace package.

ploneasgi.zopeapp.build_wsgi_app(settings)[source]#

Build the Zope WSGI application without PasteDeploy.

Replaces the [pipeline:main] section of zope.ini: make_wsgi_app is the egg:Zope#main app factory, and HTTPExceptionHandler is the egg:Zope#httpexceptions filter — mandatory, since error rendering breaks without it.

Calling this starts Zope: it opens the ZODB and fires ProcessStarting.

Parameters:

settings (Settings) -- Settings providing the zope.conf path and toggles.

Returns:

The WSGI callable to mount.

Raises:

FileNotFoundError -- If zope.conf does not exist.

Return type:

Callable[[...], Iterable[bytes]]

ploneasgi.zopeapp.check_concurrency_contract(settings)[source]#

Warn when the WSGI worker count can outrun the ZODB connection pool.

These two numbers must be coordinated or requests block waiting for a database connection under load. Body streaming is deliberately not part of this contract — it uses a separate limiter in ploneasgi.wsgi.WSGIMiddleware, because pulling bytes off a blob file holds no ZODB connection.

Parameters:

settings (Settings) -- Settings providing the configured concurrency.

Return type:

None

ploneasgi.zopeapp.lifespan(app)[source]#

Own the process lifecycle that runwsgi + waitress used to provide.

Zope startup already happened at application build time (make_wsgi_app fires ProcessStarting); what is missing under an ASGI server is the orderly database close on shutdown.

Parameters:

app (object) -- The ASGI application (unused; required by the protocol).

Yields:

Control for the lifetime of the server.

Return type:

AsyncIterator[None]