From: Géry Ogam Date: Wed, 11 Sep 2019 13:03:46 +0000 (+0200) Subject: bpo-35640: Allow passing PathLike arguments to SimpleHTTPRequestHandler (GH-11398) X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=781266ebb60e7ac781a3e07030d92275721ff3cf;p=python bpo-35640: Allow passing PathLike arguments to SimpleHTTPRequestHandler (GH-11398) --- diff --git a/Doc/library/http.server.rst b/Doc/library/http.server.rst index a367e373dc..5173decb2b 100644 --- a/Doc/library/http.server.rst +++ b/Doc/library/http.server.rst @@ -344,6 +344,9 @@ provides three different variants: If not specified, the directory to serve is the current working directory. + .. versionchanged:: 3.9 + Accepts a :term:`path-like object`. + The :class:`SimpleHTTPRequestHandler` class defines the following methods: .. method:: do_HEAD() diff --git a/Lib/http/server.py b/Lib/http/server.py index b247675ec4..005dd824f9 100644 --- a/Lib/http/server.py +++ b/Lib/http/server.py @@ -642,7 +642,7 @@ class SimpleHTTPRequestHandler(BaseHTTPRequestHandler): def __init__(self, *args, directory=None, **kwargs): if directory is None: directory = os.getcwd() - self.directory = directory + self.directory = os.fspath(directory) super().__init__(*args, **kwargs) def do_GET(self): diff --git a/Lib/test/test_httpservers.py b/Lib/test/test_httpservers.py index 87d4924a34..1c980a2fa6 100644 --- a/Lib/test/test_httpservers.py +++ b/Lib/test/test_httpservers.py @@ -14,6 +14,7 @@ import sys import re import base64 import ntpath +import pathlib import shutil import email.message import email.utils @@ -790,10 +791,10 @@ class CGIHTTPServerTestCase(BaseTestCase): class SocketlessRequestHandler(SimpleHTTPRequestHandler): - def __init__(self, *args, **kwargs): + def __init__(self, directory=None): request = mock.Mock() request.makefile.return_value = BytesIO() - super().__init__(request, None, None) + super().__init__(request, None, None, directory=directory) self.get_called = False self.protocol_version = "HTTP/1.1" @@ -1068,41 +1069,91 @@ class BaseHTTPRequestHandlerTestCase(unittest.TestCase): class SimpleHTTPRequestHandlerTestCase(unittest.TestCase): """ Test url parsing """ def setUp(self): - self.translated = os.getcwd() - self.translated = os.path.join(self.translated, 'filename') - self.handler = SocketlessRequestHandler() + self.translated_1 = os.path.join(os.getcwd(), 'filename') + self.translated_2 = os.path.join('foo', 'filename') + self.translated_3 = os.path.join('bar', 'filename') + self.handler_1 = SocketlessRequestHandler() + self.handler_2 = SocketlessRequestHandler(directory='foo') + self.handler_3 = SocketlessRequestHandler(directory=pathlib.PurePath('bar')) def test_query_arguments(self): - path = self.handler.translate_path('/filename') - self.assertEqual(path, self.translated) - path = self.handler.translate_path('/filename?foo=bar') - self.assertEqual(path, self.translated) - path = self.handler.translate_path('/filename?a=b&spam=eggs#zot') - self.assertEqual(path, self.translated) + path = self.handler_1.translate_path('/filename') + self.assertEqual(path, self.translated_1) + path = self.handler_2.translate_path('/filename') + self.assertEqual(path, self.translated_2) + path = self.handler_3.translate_path('/filename') + self.assertEqual(path, self.translated_3) + + path = self.handler_1.translate_path('/filename?foo=bar') + self.assertEqual(path, self.translated_1) + path = self.handler_2.translate_path('/filename?foo=bar') + self.assertEqual(path, self.translated_2) + path = self.handler_3.translate_path('/filename?foo=bar') + self.assertEqual(path, self.translated_3) + + path = self.handler_1.translate_path('/filename?a=b&spam=eggs#zot') + self.assertEqual(path, self.translated_1) + path = self.handler_2.translate_path('/filename?a=b&spam=eggs#zot') + self.assertEqual(path, self.translated_2) + path = self.handler_3.translate_path('/filename?a=b&spam=eggs#zot') + self.assertEqual(path, self.translated_3) def test_start_with_double_slash(self): - path = self.handler.translate_path('//filename') - self.assertEqual(path, self.translated) - path = self.handler.translate_path('//filename?foo=bar') - self.assertEqual(path, self.translated) + path = self.handler_1.translate_path('//filename') + self.assertEqual(path, self.translated_1) + path = self.handler_2.translate_path('//filename') + self.assertEqual(path, self.translated_2) + path = self.handler_3.translate_path('//filename') + self.assertEqual(path, self.translated_3) + + path = self.handler_1.translate_path('//filename?foo=bar') + self.assertEqual(path, self.translated_1) + path = self.handler_2.translate_path('//filename?foo=bar') + self.assertEqual(path, self.translated_2) + path = self.handler_3.translate_path('//filename?foo=bar') + self.assertEqual(path, self.translated_3) def test_windows_colon(self): with support.swap_attr(server.os, 'path', ntpath): - path = self.handler.translate_path('c:c:c:foo/filename') + path = self.handler_1.translate_path('c:c:c:foo/filename') + path = path.replace(ntpath.sep, os.sep) + self.assertEqual(path, self.translated_1) + path = self.handler_2.translate_path('c:c:c:foo/filename') + path = path.replace(ntpath.sep, os.sep) + self.assertEqual(path, self.translated_2) + path = self.handler_3.translate_path('c:c:c:foo/filename') path = path.replace(ntpath.sep, os.sep) - self.assertEqual(path, self.translated) + self.assertEqual(path, self.translated_3) - path = self.handler.translate_path('\\c:../filename') + path = self.handler_1.translate_path('\\c:../filename') + path = path.replace(ntpath.sep, os.sep) + self.assertEqual(path, self.translated_1) + path = self.handler_2.translate_path('\\c:../filename') + path = path.replace(ntpath.sep, os.sep) + self.assertEqual(path, self.translated_2) + path = self.handler_3.translate_path('\\c:../filename') path = path.replace(ntpath.sep, os.sep) - self.assertEqual(path, self.translated) + self.assertEqual(path, self.translated_3) - path = self.handler.translate_path('c:\\c:..\\foo/filename') + path = self.handler_1.translate_path('c:\\c:..\\foo/filename') path = path.replace(ntpath.sep, os.sep) - self.assertEqual(path, self.translated) + self.assertEqual(path, self.translated_1) + path = self.handler_2.translate_path('c:\\c:..\\foo/filename') + path = path.replace(ntpath.sep, os.sep) + self.assertEqual(path, self.translated_2) + path = self.handler_3.translate_path('c:\\c:..\\foo/filename') + path = path.replace(ntpath.sep, os.sep) + self.assertEqual(path, self.translated_3) - path = self.handler.translate_path('c:c:foo\\c:c:bar/filename') + path = self.handler_1.translate_path('c:c:foo\\c:c:bar/filename') + path = path.replace(ntpath.sep, os.sep) + self.assertEqual(path, self.translated_1) + path = self.handler_2.translate_path('c:c:foo\\c:c:bar/filename') + path = path.replace(ntpath.sep, os.sep) + self.assertEqual(path, self.translated_2) + path = self.handler_3.translate_path('c:c:foo\\c:c:bar/filename') path = path.replace(ntpath.sep, os.sep) - self.assertEqual(path, self.translated) + self.assertEqual(path, self.translated_3) class MiscTestCase(unittest.TestCase): diff --git a/Misc/NEWS.d/next/Library/2019-09-10-15-52-55.bpo-35640.X0lp5f.rst b/Misc/NEWS.d/next/Library/2019-09-10-15-52-55.bpo-35640.X0lp5f.rst new file mode 100644 index 0000000000..abdf87a623 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-09-10-15-52-55.bpo-35640.X0lp5f.rst @@ -0,0 +1,2 @@ +Allow passing a :term:`path-like object` as ``directory`` argument to the +:class:`http.server.SimpleHTTPRequestHandler` class. Patch by Géry Ogam.