This is an archive of the discontinued Mercurial Phabricator instance.

hgweb: refactor fake file object proxy for archiving
ClosedPublic

Authored by indygreg on Mar 11 2018, 12:23 AM.

Details

Summary

Python's zip file writer operates on a file object. When doing work,
it periodically calls write(), flush(), and tell() on that object.

In WSGI contexts, the start_response function returns a write()
function. That's a function to write data, not a full file object.
So, when the archival code was first introduced in 2b03c6733efa in
2006, someone invented a proxy "tellable" type that wrapped a file
object like object and kept track of write count so it could
implement tell() and satisfy zipfile's needs.

When our archival code runs, it attempts to tell() the destination
and if that fails, converts it to a "tellable" instance. Our WSGI
application passes the "wsgirequest" instance to the archival
function. It fails the tell() test and is converted to a "tellable."
It's worth noting that "wsgirequest" implements flush(), so
"tellable" doesn't.

This hackery all seems very specific to the WSGI code. So this commit
moves the "tellable" type and the conversion of the destination file
object into the WSGI code. There's a chance some other caller may be
passing a file object like object that doesn't implement tell(). But
I doubt it.

As part of the refactor, our new type implements flush() and doesn't
implement getattr. Given the intended limited use of this type,
I want things to fail fast if there is an attempt to access attributes
because I think it is important to document which attributes are being
used for what purposes.

Diff Detail

Repository
rHG Mercurial
Lint
Automatic diff as part of commit; lint not applicable.
Unit
Automatic diff as part of commit; unit tests not applicable.

Event Timeline

indygreg created this revision.Mar 11 2018, 12:23 AM
durin42 accepted this revision.Mar 12 2018, 5:12 PM
This revision is now accepted and ready to land.Mar 12 2018, 5:12 PM
This revision was automatically updated to reflect the committed changes.
martinvonz added inline comments.
mercurial/hgweb/request.py
294

s/file object like object/file-like object/ ?
s/append only/append-only/ ?

319

IIUC, the old code would forward the call via getattr, but the new code ignores it. Any practical consequence? I don't know what flush() on a WSGI request does.