Post publication hook? Hook for cleanup operations after request finished

Is there a replacement for the plone.postpublicationhook in Plone 5.2/Zope 4?

Scenario: I generated a ZIP file within a browser view which is delivered back to the client as response.
The generated temporary ZIP file should be deleted after delivery. The ZIP file is returned through a filestream_iterator. One option might be to create a custom iterator and hook the deletion into its __del__() implementation but this appears too ugly to me. Are there any other post publication hooks available in Zope 4?

The plone.postpublicationhook readme says: "The IPubBeforeCommit event is equivalent to the IAfterPublicationEvent".
Here's a bunch of them: https://github.com/zopefoundation/Zope/blob/master/src/ZPublisher/pubevents.py

https://github.com/zopefoundation/Zope/blob/8e6b9336d109e97f6e7915b4a18c57c278afcd1d/src/ZPublisher/interfaces.py#L23-L28 might be an option. Keep in mind that it will fire multiple times if requests are retried.

1 Like

There are the ZPublisher.interfaces.IPubEnd events.

For request related cleanup, BaseRequest._hold is often used. You could for example represent your zip file as a TemporaryFile and hold it via _hold until the request object is deleted.

According to the Python docs if you use tempfile.TemporaryFile then the file is "destroyed as soon as it is closed (including an implicit close when the object is garbage collected)".

I would try that.

May can anyone of you point me to a code that works out of the box?
I tried this but the event never fires:

from Products.CMFCore.interfaces import ISiteRoot
from ZPublisher.pubevents import IPubBeforeCommit

def pubend(**kwargs):
    print(kwargs)

gsm = zope.component.getGlobalSiteManager()
gsm.registerHandler(pubend, (ISiteRoot, IPubBeforeCommit))

I also tried ZPublisher.interfaces.IPubEnd which does not work either.

What works on the other hand is this:

from Products.CMFCore.interfaces import ISiteRoot
from zope.traversing.interfaces import IBeforeTraverseEvent
gsm = zope.component.getGlobalSiteManager()
gsm.registerHandler(hookTraverse, (ISiteRoot, IBeforeTraverseEvent))

But in my case I need a hook just before the response to the browser goes out. And then inside the hook I need access to the request and the response.

It can not see where there was an explicit example in this thread.