Ticket #2625: 2625.3.patch

File 2625.3.patch, 8.4 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")
    10091010
    1010     def testStringConversion(self):
     1011    def test_stringConversion(self):
    10111012        self.assertEquals(str(self.path), "http://example.com/foo/bar?yes=no&no=yes#footer")
    10121013
    1013     def testChildString(self):
     1014    def test_childString(self):
    10141015        self.assertEquals(str(self.path.child('hello')), "http://example.com/foo/bar/hello")
    10151016        self.assertEquals(str(self.path.child('hello').child('')), "http://example.com/foo/bar/hello/")
    10161017
    1017     def testSiblingString(self):
     1018    def test_siblingString(self):
    10181019        self.assertEquals(str(self.path.sibling('baz')), 'http://example.com/foo/baz')
    10191020
    10201021        # The sibling of http://example.com/foo/bar/
     
    10231024        # http://example.com/foo/bar/index.html
    10241025        self.assertEquals(str(self.path.child('').sibling('baz')), 'http://example.com/foo/bar/baz')
    10251026
    1026     def testParentString(self):
     1027    def test_parentString(self):
    10271028        # parent should be equivalent to '..'
    10281029        # 'foo' is the current directory, '/' is the parent directory
    10291030        self.assertEquals(str(self.path.parent()), 'http://example.com/')
     
    10311032        self.assertEquals(str(self.path.child('baz').parent()), 'http://example.com/foo/')
    10321033        self.assertEquals(str(self.path.parent().parent().parent().parent().parent()), 'http://example.com/')
    10331034
    1034     def testHereString(self):
     1035    def test_hereString(self):
    10351036        # here should be equivalent to '.'
    10361037        self.assertEquals(str(self.path.here()), 'http://example.com/foo/')
    10371038        self.assertEquals(str(self.path.child('').here()), 'http://example.com/foo/bar/')
    1038 
     1039       
     1040    def test_fromStringQuote(self):
     1041        """
     1042        Test that an URLPath constructed using C{fromStringQuote} is properly escaped.
     1043        """
     1044        self.assertEquals(str(self.quotedpath), "http://example.com/foo/hello%20there?yes=no&no=yes#footer")
     1045       
     1046    def test_childQuotedString(self):
     1047        """
     1048        This test checks if child path with spaces and slashes is handled in least surprising way:
     1049        properly escaped and result in single segment path amendment.
     1050        """
     1051        #child() with quotes (",') and slashes  should be properly escaped
     1052        self.assertEquals(str(self.path.childQuote("hello/ there")), 'http://example.com/foo/bar/hello%2F%20there')
     1053       
     1054    def test_siblingQuotedString(self):
     1055        """
     1056        This test checks if sibling path with spaces and slashes is handled in least surprising way:
     1057        properly escaped and result in single segment path amendment.
     1058        """
     1059        #child() with quotes (",') and slashes  should be properly escaped
     1060        self.assertEquals(str(self.path.siblingQuote("hello/ there")), 'http://example.com/foo/hello%2F%20there')
  • twisted/python/urlpath.py

     
    1919    _qpathlist = None
    2020    _uqpathlist = None
    2121   
    22     def pathList(self, unquote=0, copy=1):
     22    def pathList(self, unquote=False, copy=True):
    2323        if self._qpathlist is None:
    2424            self._qpathlist = self.path.split('/')
    2525            self._uqpathlist = map(urllib.unquote, self._qpathlist)
     
    3333            return result
    3434
    3535    def fromString(klass, st):
     36        """
     37        Create a new URLPath from a url string.
     38       
     39        @param st: the url string.  Path segments should be quoted already.
     40        @type st: C{str}
     41       
     42        @return: A new L{URLPath} object
     43        @rtype: L{URLPath}
     44        """
    3645        t = urlparse.urlsplit(st)
    3746        u = klass(*t)
    3847        return u
    3948
    4049    fromString = classmethod(fromString)
     50   
     51    def fromStringQuote(klass, st):
     52        """
     53        Create a new URLPath from a url string.
     54       
     55        @param st: the url string.  Path segments should not be quoted.
     56        @type st: C{str}
     57       
     58        @return: A new L{URLPath} object
     59        @rtype: L{URLPath}
     60        """
     61        t = urlparse.urlsplit(st)
     62       
     63        # Quote each path segment
     64        quotedpathparts = [urllib.quote(segment, '')
     65                           for segment in t.path.split('/')]
     66        newpath = '/'.join(quotedpathparts)
     67        u = klass(scheme=t.scheme, netloc=t.netloc, path=newpath,
     68                  query=t.query, fragment=t.fragment)
     69        return u
     70   
     71    fromStringQuote = classmethod(fromStringQuote)
    4172
    4273    def fromRequest(klass, request):
    4374        return klass.fromString(request.prePathURL())
     
    5485                        '/'.join(newpathsegs),
    5586                        query)
    5687
    57     def sibling(self, path, keepQuery=0):
     88    def sibling(self, path, keepQuery=False):
     89        """
     90        Create a new URLPath with the last path segment replaced. 
     91     
     92        @param path: new path segment. The path argument should be quoted already.
     93        @type path: C{str}
     94        @param keepQuery: if set to True, will keep the query part of URL, 
     95                          else (and by default) will strip the query part.
     96        @type keepQuery: C{bool}
     97        @return: A new L{URLPath} object with the new last path segment
     98        @rtype: L{URLPath}
     99        """
    58100        l = self.pathList()
    59101        l[-1] = path
    60102        return self._pathMod(l, keepQuery)
     103   
     104    def siblingQuote(self, path, keepQuery=False):
     105        """
     106        Create a new URLPath with the last path segment replaced. 
     107     
     108        @param path: new path segment. The path argument should not be quoted.
     109        @type path: C{str}
     110        @param keepQuery: if set to True, will keep the query part of URL, 
     111                          else (and by default) will strip the query part.
     112        @type keepQuery: C{bool}
     113        @return: A new L{URLPath} object with the new last path segment
     114        @rtype: L{URLPath}
     115        """
     116        #Clean up path with urlescaped version
     117        quotedPath = urllib.quote(path,'')
     118        l = self.pathList()
     119        l[-1] = quotedPath
     120        return self._pathMod(l, keepQuery)
    61121
    62     def child(self, path, keepQuery=0):
     122    def child(self, path, keepQuery=False):
     123        """
     124        Create a new URLPath with an added child segment. 
     125     
     126        @param path: path segment to add. The path argument should be quoted already.
     127        @type path: C{str}
     128        @param keepQuery: if set to True, will keep the query part of URL, 
     129                          else (and by default) will strip the query part.
     130        @type keepQuery: C{bool}
     131        @return: A new L{URLPath} object with path appended to current object
     132        @rtype: L{URLPath}
     133        """
    63134        l = self.pathList()
    64135        if l[-1] == '':
    65136            l[-1] = path
    66137        else:
    67138            l.append(path)
    68139        return self._pathMod(l, keepQuery)
     140   
     141    def childQuote(self, path, keepQuery=False):
     142        """
     143        Create a new URLPath with an added child segment. 
     144     
     145        @param path: path segment to add. The path argument should not be quoted.
     146        @type path: C{str}
     147        @param keepQuery: if set to True, will keep the query part of URL, 
     148                          else (and by default) will strip the query part.
     149        @type keepQuery: C{bool}
     150        @return: A new L{URLPath} object with path appended to current object
     151        @rtype: L{URLPath}
     152        """
     153        #Clean up path with urlescaped version
     154        quotedPath = urllib.quote(path,'')
     155        l = self.pathList()
     156        if l[-1] == '':
     157            l[-1] = quotedPath
     158        else:
     159            l.append(quotedPath)
     160        return self._pathMod(l, keepQuery)
    69161
    70     def parent(self, keepQuery=0):
     162    def parent(self, keepQuery=False):
    71163        l = self.pathList()
    72164        if l[-1] == '':
    73165            del l[-2]
     
    78170            l[-1] = ''
    79171        return self._pathMod(l, keepQuery)
    80172
    81     def here(self, keepQuery=0):
     173    def here(self, keepQuery=False):
    82174        l = self.pathList()
    83175        if l[-1] != '':
    84176            l[-1] = ''