Ticket #2625: 2625.4.patch

File 2625.4.patch, 9.2 KB (added by danben, 7 years ago)
  • twisted/test/test_paths.py

     
    10061006class URLPathTestCase(unittest.TestCase):
    10071007    def setUp(self):
    10081008        self.path = urlpath.URLPath.fromString("http://example.com/foo/bar?yes=no&no=yes#footer")
     1009        self.quotedpath = urlpath.URLPath.fromStringQuote("http://example.com/foo/hello there?yes=no&no=yes#footer")
     1010        self.assertEquals(len(URLPathTestCase.flushWarnings(self, None)), 1)
    10091011
    1010     def testStringConversion(self):
     1012    def test_stringConversion(self):
    10111013        self.assertEquals(str(self.path), "http://example.com/foo/bar?yes=no&no=yes#footer")
    10121014
    1013     def testChildString(self):
     1015    def test_childString(self):
    10141016        self.assertEquals(str(self.path.child('hello')), "http://example.com/foo/bar/hello")
    10151017        self.assertEquals(str(self.path.child('hello').child('')), "http://example.com/foo/bar/hello/")
     1018        self.assertEquals(len(URLPathTestCase.flushWarnings(self, None)), 3)
    10161019
    1017     def testSiblingString(self):
     1020    def test_siblingString(self):
    10181021        self.assertEquals(str(self.path.sibling('baz')), 'http://example.com/foo/baz')
    10191022
    10201023        # The sibling of http://example.com/foo/bar/
     
    10221025        # because really we are constructing a sibling of
    10231026        # http://example.com/foo/bar/index.html
    10241027        self.assertEquals(str(self.path.child('').sibling('baz')), 'http://example.com/foo/bar/baz')
     1028        self.assertEquals(len(URLPathTestCase.flushWarnings(self, None)), 3)
    10251029
    1026     def testParentString(self):
     1030    def test_parentString(self):
    10271031        # parent should be equivalent to '..'
    10281032        # 'foo' is the current directory, '/' is the parent directory
    10291033        self.assertEquals(str(self.path.parent()), 'http://example.com/')
     
    10311035        self.assertEquals(str(self.path.child('baz').parent()), 'http://example.com/foo/')
    10321036        self.assertEquals(str(self.path.parent().parent().parent().parent().parent()), 'http://example.com/')
    10331037
    1034     def testHereString(self):
     1038    def test_hereString(self):
    10351039        # here should be equivalent to '.'
    10361040        self.assertEquals(str(self.path.here()), 'http://example.com/foo/')
    10371041        self.assertEquals(str(self.path.child('').here()), 'http://example.com/foo/bar/')
    1038 
     1042       
     1043    def test_fromStringQuote(self):
     1044        """
     1045        Test that an URLPath constructed using C{fromStringQuote} is properly escaped.
     1046        """
     1047        self.assertEquals(str(self.quotedpath), "http://example.com/foo/hello%20there?yes=no&no=yes#footer")
     1048       
     1049    def test_childQuotedString(self):
     1050        """
     1051        This test checks if child path with spaces and slashes is handled in least surprising way:
     1052        properly escaped and result in single segment path amendment.
     1053        """
     1054        #child() with quotes (",') and slashes  should be properly escaped
     1055        self.assertEquals(str(self.path.childQuote("hello/ there")), 'http://example.com/foo/bar/hello%2F%20there')
     1056       
     1057    def test_siblingQuotedString(self):
     1058        """
     1059        This test checks if sibling path with spaces and slashes is handled in least surprising way:
     1060        properly escaped and result in single segment path amendment.
     1061        """
     1062        #child() with quotes (",') and slashes  should be properly escaped
     1063        self.assertEquals(str(self.path.siblingQuote("hello/ there")), 'http://example.com/foo/hello%2F%20there')
  • twisted/python/urlpath.py

     
    66
    77import urlparse
    88import urllib
     9import warnings
    910
    1011class URLPath:
    1112    def __init__(self, scheme='', netloc='localhost', path='',
     
    1920    _qpathlist = None
    2021    _uqpathlist = None
    2122   
    22     def pathList(self, unquote=0, copy=1):
     23    def pathList(self, unquote=False, copy=True):
    2324        if self._qpathlist is None:
    2425            self._qpathlist = self.path.split('/')
    2526            self._uqpathlist = map(urllib.unquote, self._qpathlist)
     
    3334            return result
    3435
    3536    def fromString(klass, st):
     37        """
     38        Create a new URLPath from a url string.
     39       
     40        @param st: the url string.  Path segments should be quoted already.
     41        @type st: C{str}
     42       
     43        @return: A new L{URLPath} object
     44        @rtype: L{URLPath}
     45        """
     46        warnings.warn("fromString will be deprecated.  Use fromStringQuote instead.", category=PendingDeprecationWarning)
    3647        t = urlparse.urlsplit(st)
    3748        u = klass(*t)
    3849        return u
    3950
    4051    fromString = classmethod(fromString)
     52   
     53    def fromStringQuote(klass, st):
     54        """
     55        Create a new URLPath from a url string.
     56       
     57        @param st: the url string.  Path segments should not be quoted.
     58        @type st: C{str}
     59       
     60        @return: A new L{URLPath} object
     61        @rtype: L{URLPath}
     62        """
     63        t = urlparse.urlsplit(st)
     64       
     65        # Quote each path segment
     66        quotedpathparts = [urllib.quote(segment, '')
     67                           for segment in t.path.split('/')]
     68        newpath = '/'.join(quotedpathparts)
     69        u = klass(scheme=t.scheme, netloc=t.netloc, path=newpath,
     70                  query=t.query, fragment=t.fragment)
     71        return u
     72   
     73    fromStringQuote = classmethod(fromStringQuote)
    4174
    4275    def fromRequest(klass, request):
    4376        return klass.fromString(request.prePathURL())
     
    5487                        '/'.join(newpathsegs),
    5588                        query)
    5689
    57     def sibling(self, path, keepQuery=0):
     90    def sibling(self, path, keepQuery=False):
     91        """
     92        Create a new URLPath with the last path segment replaced. 
     93     
     94        @param path: new path segment. The path argument should be quoted already.
     95        @type path: C{str}
     96        @param keepQuery: if set to True, will keep the query part of URL, 
     97                          else (and by default) will strip the query part.
     98        @type keepQuery: C{bool}
     99        @return: A new L{URLPath} object with the new last path segment
     100        @rtype: L{URLPath}
     101        """
     102        warnings.warn("sibling will be deprecated.  Use siblingQuote instead.", category=PendingDeprecationWarning)
    58103        l = self.pathList()
    59104        l[-1] = path
    60105        return self._pathMod(l, keepQuery)
     106   
     107    def siblingQuote(self, path, keepQuery=False):
     108        """
     109        Create a new URLPath with the last path segment replaced. 
     110     
     111        @param path: new path segment. The path argument should not be quoted.
     112        @type path: C{str}
     113        @param keepQuery: if set to True, will keep the query part of URL, 
     114                          else (and by default) will strip the query part.
     115        @type keepQuery: C{bool}
     116        @return: A new L{URLPath} object with the new last path segment
     117        @rtype: L{URLPath}
     118        """
     119        #Clean up path with urlescaped version
     120        quotedPath = urllib.quote(path,'')
     121        l = self.pathList()
     122        l[-1] = quotedPath
     123        return self._pathMod(l, keepQuery)
    61124
    62     def child(self, path, keepQuery=0):
     125    def child(self, path, keepQuery=False):
     126        """
     127        Create a new URLPath with an added child segment. 
     128     
     129        @param path: path segment to add. The path argument should be quoted already.
     130        @type path: C{str}
     131        @param keepQuery: if set to True, will keep the query part of URL, 
     132                          else (and by default) will strip the query part.
     133        @type keepQuery: C{bool}
     134        @return: A new L{URLPath} object with path appended to current object
     135        @rtype: L{URLPath}
     136        """
     137        warnings.warn("child will be deprecated.  Use childQuote instead.", category=PendingDeprecationWarning)
    63138        l = self.pathList()
    64139        if l[-1] == '':
    65140            l[-1] = path
    66141        else:
    67142            l.append(path)
    68143        return self._pathMod(l, keepQuery)
     144   
     145    def childQuote(self, path, keepQuery=False):
     146        """
     147        Create a new URLPath with an added child segment. 
     148     
     149        @param path: path segment to add. The path argument should not be quoted.
     150        @type path: C{str}
     151        @param keepQuery: if set to True, will keep the query part of URL, 
     152                          else (and by default) will strip the query part.
     153        @type keepQuery: C{bool}
     154        @return: A new L{URLPath} object with path appended to current object
     155        @rtype: L{URLPath}
     156        """
     157        #Clean up path with urlescaped version
     158        quotedPath = urllib.quote(path,'')
     159        l = self.pathList()
     160        if l[-1] == '':
     161            l[-1] = quotedPath
     162        else:
     163            l.append(quotedPath)
     164        return self._pathMod(l, keepQuery)
    69165
    70     def parent(self, keepQuery=0):
     166    def parent(self, keepQuery=False):
    71167        l = self.pathList()
    72168        if l[-1] == '':
    73169            del l[-2]
     
    78174            l[-1] = ''
    79175        return self._pathMod(l, keepQuery)
    80176
    81     def here(self, keepQuery=0):
     177    def here(self, keepQuery=False):
    82178        l = self.pathList()
    83179        if l[-1] != '':
    84180            l[-1] = ''