Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

9438 py2 bytes directory listing #1008

Merged
merged 6 commits into from
May 7, 2018

Conversation

markrwilliams
Copy link
Member

Contributor Checklist:

Copy link
Member

@glyph glyph left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new test looks good, and the proposed change fixes it in a way which seems reasonably compatible.

If you want to address any of the minor feedback inline, feel free to do so either as a tweak before landing or as a follow-up.

Return a resource that generates an HTML listing of the
directory this path represents.

@return: A L{resource.Resource} that renders the directory to
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that DirectoryLister is public, this could refer directly to that.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is it public though. 😭

path = self.path
names = self.listNames()
else:
# DirectoryLister works in terms of native strings, so on
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we not need to do the inverse (.asTextMode()) on PY3 then?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, but for a bad reason: File and DirectoryLister are tricky.

getChild now decodes all descendant paths to text, so that by the time the empty path is reached and directoryListing called, the path given to DirectoryLister is guaranteed to be text, unless of course the path being listed is the File's own path.

Given:

from twisted.web import server, static
from twisted.internet import defer, endpoints, task


@task.react
def main(reactor):
    site = server.Site(static.File(b"/path/to/some/directory/"))
    listener = endpoints.serverFromString(reactor, "tcp:8080")
    d = listener.listen(site)

    @d.addCallback
    def _(_):
        return defer.Deferred()

    return d

Assuming that /path/to/some/directory/child exists, accessing http://localhost:8080/child/ or any other descendant creates a DirectoryLister with a text path. Accessing http://localhost:8080/, however, creates one with a bytes path.

Surprise! On Python 3, this is fine. That's DirectoryLister itself decodes bytes descendants to text on Python 3.

So the actual admitted by DirectoryLister is:

DirectoryLister parameter Python 3 Python 2
pathname str or bytes str
dirs str or bytes str
contentTypes dict of str dict of str
contentEncodings dict of str dict of str
defaultType str str

Which is not exactly what I said in the commit message, but does mean this part of the PR is correct (I think.)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Every day I'm a little more sympathetic towards web2's abandonment of this API :).

self.assertIsInstance(response, bytes)
if sys.getfilesystemencoding().lower() not in ('utf-8', 'mcbs'):
test_emptyChildUnicodeParent.skip = (
"Cannot write unicode filenames with file system encoding of"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ITYM "non-ASCII"? Given that the u'' child is the one we care about, I'm pretty sure that will survive most boneheaded filesystem encodings, and this skip could be removed?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a safeguard I carried over from another test, because who knows what sys.getfilesystemencoding, which FilePath uses, is going to return. But as you point out, it should be impossible that SynchronousTestCase.mkstemp().decode(sys.getfilesystemencoding()) + u'' could return an unencodable path, so this skip is unnecessary.

It should be impossible for
SynchronousTestCase.mkstemp().decode(sys.getfilesystemencoding()) +
u'' to return an unencodable path, so the skip is unnecessary.
@markrwilliams markrwilliams merged commit 982c9ce into trunk May 7, 2018
@markrwilliams markrwilliams deleted the 9438-py2-bytes-directory-listing branch May 7, 2018 14:14
@whalebot-helmsman
Copy link

Is there a plan to release new twisted version with this fix?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants