Ticket #2625: 2625.4.patch

File 2625.4.patch, 9.2 KB (added by danben, 4 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] = ''