/usr/lib/python3/dist-packages/urlobject/path.py is in python3-urlobject 2.3.4-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 | # -*- coding: utf-8 -*-
import posixpath
import urllib
from .compat import urlparse
from six import text_type, u
class Root(object):
"""A descriptor which always returns the root path."""
def __get__(self, instance, cls):
return cls('/')
class URLPath(text_type):
root = Root()
def __repr__(self):
return u('URLPath(%r)') % (text_type(self),)
@classmethod
def join_segments(cls, segments, absolute=True):
"""Create a :class:`URLPath` from an iterable of segments."""
if absolute:
path = cls('/')
else:
path = cls('')
for segment in segments:
path = path.add_segment(segment)
return path
@property
def segments(self):
"""
Split this path into (decoded) segments.
>>> URLPath('/a/b/c').segments
('a', 'b', 'c')
Non-leaf nodes will have a trailing empty string, and percent encodes
will be decoded:
>>> URLPath('/a%20b/c%20d/').segments
('a b', 'c d', '')
"""
segments = tuple(map(path_decode, self.split('/')))
if segments[0] == '':
return segments[1:]
return segments
@property
def parent(self):
"""
The parent of this node.
>>> URLPath('/a/b/c').parent
URLPath('/a/b/')
>>> URLPath('/foo/bar/').parent
URLPath('/foo/')
"""
if self.is_leaf:
return self.relative('.')
return self.relative('..')
@property
def is_leaf(self):
"""
Is this path a leaf node?
>>> URLPath('/a/b/c').is_leaf
True
>>> URLPath('/a/b/').is_leaf
False
"""
return self and self.segments[-1] != '' or False
@property
def is_relative(self):
"""
Is this path relative?
>>> URLPath('a/b/c').is_relative
True
>>> URLPath('/a/b/c').is_relative
False
"""
return self[0] != '/'
@property
def is_absolute(self):
"""
Is this path absolute?
>>> URLPath('a/b/c').is_absolute
False
>>> URLPath('/a/b/c').is_absolute
True
"""
return self[0] == '/'
def relative(self, rel_path):
"""
Resolve a relative path against this one.
>>> URLPath('/a/b/c').relative('.')
URLPath('/a/b/')
>>> URLPath('/a/b/c').relative('d')
URLPath('/a/b/d')
>>> URLPath('/a/b/c').relative('../d')
URLPath('/a/d')
"""
return type(self)(urlparse.urljoin(self, rel_path))
def add_segment(self, segment):
"""
Add a segment to this path.
>>> URLPath('/a/b/').add_segment('c')
URLPath('/a/b/c')
Non-ASCII and reserved characters (including slashes) will be encoded:
>>> URLPath('/a/b/').add_segment('dé/f')
URLPath('/a/b/d%C3%A9%2Ff')
"""
return type(self)(posixpath.join(self, path_encode(segment)))
def add(self, path):
"""
Add a partial path to this one.
The only difference between this and :meth:`add_segment` is that slash
characters will not be encoded, making it suitable for adding more than
one path segment at a time:
>>> URLPath('/a/b/').add('dé/f/g')
URLPath('/a/b/d%C3%A9/f/g')
"""
return type(self)(posixpath.join(self, path_encode(path, safe='/')))
def _path_encode_py2(s, safe=''):
"""Quote unicode or str using path rules."""
if isinstance(s, unicode):
s = s.encode('utf-8')
if isinstance(safe, unicode):
safe = safe.encode('utf-8')
return urllib.quote(s, safe=safe).decode('utf-8')
def _path_encode_py3(s, safe=''):
"""Quote str or bytes using path rules."""
# s can be bytes or unicode, urllib.parse.quote() assumes
# utf-8 if encoding is necessary.
return urlparse.quote(s, safe=safe)
def _path_decode_py2(s):
"""Unquote unicode or str using path rules."""
if isinstance(s, unicode):
s = s.encode('utf-8')
return urllib.unquote(s).decode('utf-8')
def _path_decode_py3(s):
"""Unquote str or bytes using path rules."""
if isinstance(s, bytes):
s = s.decode('utf-8')
return urlparse.unquote(s)
if hasattr(urllib, 'quote'):
path_encode = _path_encode_py2
path_decode = _path_decode_py2
del _path_encode_py3
del _path_decode_py3
else:
path_encode = _path_encode_py3
path_decode = _path_decode_py3
del _path_encode_py2
del _path_decode_py2
|