Ticket #2625: 2625.6.patch

File 2625.6.patch, 6.9 KB (added by magmatt, 9 months ago)
  • twisted/python/test/test_urlpath.py

    diff --git twisted/python/test/test_urlpath.py twisted/python/test/test_urlpath.py
    index 4919cdc..aa86ecb 100644
     
    4242        self.assertEqual(str(self.path.here()), 'http://example.com/foo/') 
    4343        self.assertEqual(str(self.path.child('').here()), 'http://example.com/foo/bar/') 
    4444 
     45 
     46    def test_child_noQuote(self): 
     47        """ 
     48        C{child} should not quote special characters when quoting is disabled 
     49        (default). 
     50        """ 
     51        path = urlpath.URLPath.fromString('http://example.com/foo/bar') 
     52        self.assertEquals(str(path.child('" +-\\/')), 
     53                          'http://example.com/foo/bar/" +-\\/') 
     54 
     55 
     56    def test_child_quote(self): 
     57        """ 
     58        C{child} should quote special characters when quoting is enabled 
     59        """ 
     60        path = urlpath.URLPath.fromString('http://example.com/foo/bar', 
     61                                          quote=True) 
     62        self.assertEquals(str(path.child('" +-\\/')), 
     63                          'http://example.com/foo/bar/%22%20%2B-%5C%2F') 
     64        self.assertEquals(str(path.child('').child('"/')), 
     65                          'http://example.com/foo/bar/%22%2F') 
     66 
     67 
     68    def test_sibling_noQuote(self): 
     69        """ 
     70        C{sibling} should not quote special characters when quoting is disabled 
     71        (default behavior). 
     72        """ 
     73        path = urlpath.URLPath.fromString('http://example.com/foo/bar') 
     74        self.assertEquals(str(path.sibling('"+/')), 
     75                          'http://example.com/foo/"+/') 
     76 
     77 
     78    def test_sibling_quote(self): 
     79        """ 
     80        C{sibling} should quote special characters when quoting is enabled. 
     81        """ 
     82        path = urlpath.URLPath.fromString('http://example.com/foo/bar', 
     83                                          quote=True) 
     84        self.assertEquals(str(path.sibling('"+/')), 
     85                          'http://example.com/foo/%22%2B%2F') 
     86 
     87 
     88    def test_click_noQuote(self): 
     89        """ 
     90        The object returned by C{click} should not quote special characters by 
     91        default. 
     92        """ 
     93        path = urlpath.URLPath.fromString('http://example.com/foo/bar') 
     94        self.assertEquals(str(path.click('foo/bar').child('+/')), 
     95                          'http://example.com/foo/foo/bar/+/') 
     96 
     97 
     98    def test_click_quote(self): 
     99        """ 
     100        The object returned by C{click} should inherit the quoting behavior of 
     101        the base L{URLPath} 
     102        """ 
     103        path = urlpath.URLPath.fromString('http://example.com/foo/bar', 
     104                                          quote=True) 
     105        self.assertEquals(str(path.click('foo/bar').child('+/')), 
     106                          'http://example.com/foo/foo/bar/%2B%2F')         
     107 
     108 
  • twisted/python/urlpath.py

    diff --git twisted/python/urlpath.py twisted/python/urlpath.py
    index 1c15f09..a8eeb68 100644
     
    88import urllib 
    99 
    1010class URLPath: 
     11    """ 
     12    @ivar _quote: See L{__init__} 
     13    """ 
    1114    def __init__(self, scheme='', netloc='localhost', path='', 
    12                  query='', fragment=''): 
     15                 query='', fragment='', quote=False): 
     16        """ 
     17        @param quote: If C{False} (default) then I won't quote path segments 
     18            passed to L{sibling} or L{child} (the caller is responsible for 
     19            doing any needed quoting in this case). 
     20            If C{True} then I will quote path segments, and the caller 
     21            I{should not} quote the path segments. 
     22        """ 
    1323        self.scheme = scheme or 'http' 
    1424        self.netloc = netloc 
    1525        self.path = path or '/' 
    1626        self.query = query 
    1727        self.fragment = fragment 
     28        self._quote = quote 
    1829 
    1930    _qpathlist = None 
    2031    _uqpathlist = None 
     32    _quote = False 
    2133     
    2234    def pathList(self, unquote=0, copy=1): 
    2335        if self._qpathlist is None: 
     
    3244        else: 
    3345            return result 
    3446 
    35     def fromString(klass, st): 
     47    def fromString(klass, st, quote=False): 
     48        """ 
     49        Create a L{URLPath} from a string. 
     50 
     51        @param st: A I{quoted} url. 
     52        @param quote: See L{__init__} 
     53        """ 
    3654        t = urlparse.urlsplit(st) 
    37         u = klass(*t) 
     55        u = klass(*t, quote=quote) 
    3856        return u 
    3957 
    4058    fromString = classmethod(fromString) 
     
    5270        return URLPath(self.scheme, 
    5371                        self.netloc, 
    5472                        '/'.join(newpathsegs), 
    55                         query) 
     73                        query, 
     74                        quote=self._quote) 
     75 
    5676 
    57     def sibling(self, path, keepQuery=0): 
     77    def _maybeQuoteSegment(self, segment): 
     78        """ 
     79        Return the URL quoted version of C{segment} if quoting is enabled (see 
     80        L{__init__.quote<__init__>}) otherwise return C{segment} as-is. 
     81        """ 
     82        if self._quote: 
     83            return urllib.quote(segment, '') 
     84        else: 
     85            return segment 
     86 
     87 
     88    def sibling(self, path, keepQuery=False): 
    5889        l = self.pathList() 
    59         l[-1] = path 
     90        l[-1] = self._maybeQuoteSegment(path) 
    6091        return self._pathMod(l, keepQuery) 
    6192 
    62     def child(self, path, keepQuery=0): 
     93 
     94    def child(self, path, keepQuery=False): 
     95        """ 
     96        Add a child segment to URL path part.  
     97         
     98        @param path: The path segment to add.  The segment should be quoted 
     99            (using L{urllib.quote} for instance) unless I have been told to 
     100            do the quoting (see L{__init.quote<__init__>}). 
     101        @type path: C{str} 
     102 
     103        @param keepQuery: If set to True, keep the current query part in the 
     104            result, otherwise discard it. 
     105        @type keepQuery: C{bool} 
     106 
     107        @return: A new L{URLPath} object with the same values as this one, 
     108            but with C{path} added as a new segment to the path. 
     109        @rtype: L{URLPath} 
     110        """ 
     111        # Store the quoted version 
     112        fixedPath = self._maybeQuoteSegment(path) 
    63113        l = self.pathList() 
    64114        if l[-1] == '': 
    65             l[-1] = path 
     115            l[-1] = fixedPath 
    66116        else: 
    67             l.append(path) 
     117            l.append(fixedPath) 
    68118        return self._pathMod(l, keepQuery) 
    69119 
    70     def parent(self, keepQuery=0): 
     120 
     121    def parent(self, keepQuery=False): 
    71122        l = self.pathList() 
    72123        if l[-1] == '': 
    73124            del l[-2] 
     
    78129            l[-1] = '' 
    79130        return self._pathMod(l, keepQuery) 
    80131 
    81     def here(self, keepQuery=0): 
     132    def here(self, keepQuery=False): 
    82133        l = self.pathList() 
    83134        if l[-1] != '': 
    84135            l[-1] = '' 
     
    106157                        netloc, 
    107158                        path, 
    108159                        query, 
    109                         fragment) 
     160                        fragment, 
     161                        quote=self._quote) 
    110162 
    111163 
    112164