URL manipulation made simple.
65
The Path class provides comprehensive URL path manipulation with segment-based access, automatic percent-encoding/decoding, and support for both absolute and relative paths. Path objects handle the complexities of URL path formatting while providing an intuitive interface.
Create and load path objects from strings with automatic segment parsing and encoding handling.
class Path:
def __init__(self, path='', force_absolute=lambda _: False, strict=False):
"""
Initialize a Path object.
Args:
path (str): Path string to parse
force_absolute (callable): Function to determine if path should be absolute
strict (bool): Enable strict parsing mode
"""
def load(self, path):
"""
Load a path string into the Path object.
Args:
path (str): Path string to parse and load
Returns:
Path: Self for method chaining
"""Usage:
from furl import Path
# Create from string
p = Path('/api/v1/users')
print(p.segments) # ['api', 'v1', 'users']
# Create empty path
p = Path()
p.load('/new/path/here')
print(p.segments) # ['new', 'path', 'here']
# Relative path
rel_path = Path('relative/path')
print(rel_path.isabsolute) # FalseDirect manipulation of path segments with automatic encoding and path reconstruction.
class Path:
@property
def segments(self) -> list[str]:
"""
List of path segments (percent-decoded).
Segments are automatically decoded and can be manipulated directly.
"""
@segments.setter
def segments(self, segments: list[str]):
"""Set path segments list"""
def add(self, path):
"""
Add path segments to the existing path.
Args:
path (str): Path string with segments to add
Returns:
Path: Self for method chaining
"""
def set(self, path):
"""
Set the path, replacing all existing segments.
Args:
path (str): New path string
Returns:
Path: Self for method chaining
"""
def remove(self, path):
"""
Remove path segments.
Args:
path (str|bool): Path segments to remove, or True to remove all
Returns:
Path: Self for method chaining
"""Usage:
p = Path('/api/v1')
# Direct segment manipulation
p.segments.append('users')
p.segments.append('123')
print(str(p)) # '/api/v1/users/123'
# Add path segments
p.add('profile')
print(str(p)) # '/api/v1/users/123/profile'
# Set new path (replaces existing)
p.set('/different/path')
print(p.segments) # ['different', 'path']
# Remove segments
p.remove('path')
print(p.segments) # ['different']
# Remove all segments
p.remove(True)
print(str(p)) # '/'Access path characteristics and metadata.
class Path:
@property
def isabsolute(self) -> bool:
"""
Boolean indicating if path is absolute (starts with /).
For URL paths with netloc, this becomes read-only True.
"""
@isabsolute.setter
def isabsolute(self, isabsolute: bool):
"""Set absolute path flag (may be read-only in URL context)"""
@property
def isdir(self) -> bool:
"""
Boolean indicating if path represents a directory.
True if path ends with empty segment (trailing slash).
"""
@property
def isfile(self) -> bool:
"""
Boolean indicating if path represents a file.
True if path doesn't end with empty segment (no trailing slash).
"""Usage:
# Directory path (ends with /)
dir_path = Path('/api/v1/')
print(dir_path.isdir) # True
print(dir_path.isfile) # False
print(dir_path.segments) # ['api', 'v1', '']
# File path (no trailing /)
file_path = Path('/api/v1/users')
print(file_path.isdir) # False
print(file_path.isfile) # True
# Absolute vs relative
abs_path = Path('/absolute/path')
print(abs_path.isabsolute) # True
rel_path = Path('relative/path')
print(rel_path.isabsolute) # False
# Make relative path absolute
rel_path.isabsolute = True
print(str(rel_path)) # '/relative/path'Normalize paths by resolving relative references and cleaning segments.
class Path:
def normalize(self):
"""
Normalize the path by resolving . and .. segments.
Returns:
Path: Self for method chaining
"""Usage:
# Path with relative references
messy_path = Path('/api/../api/v1/./users/../users')
print(messy_path.segments) # ['api', '..', 'api', 'v1', '.', 'users', '..', 'users']
messy_path.normalize()
print(messy_path.segments) # ['api', 'v1', 'users']
print(str(messy_path)) # '/api/v1/users'Convert paths to strings and perform path operations.
class Path:
def __str__(self) -> str:
"""
Convert path to string with proper encoding.
Returns:
str: Percent-encoded path string
"""
def __truediv__(self, path) -> 'Path':
"""
Path division operator (/) for joining paths.
Args:
path (str): Path segment to join
Returns:
Path: New Path object with joined path
"""
def __eq__(self, other) -> bool:
"""Check path equality"""
def __bool__(self) -> bool:
"""Boolean evaluation (True if path has segments)"""
def asdict(self) -> dict:
"""
Convert path to dictionary representation.
Returns:
dict: Dictionary with path metadata
"""Usage:
base_path = Path('/api/v1')
# String conversion with encoding
path_with_spaces = Path('/path with spaces/and special chars!')
print(str(path_with_spaces)) # '/path%20with%20spaces/and%20special%20chars!'
# Path joining with / operator
full_path = base_path / 'users' / '123'
print(str(full_path)) # '/api/v1/users/123'
# Path comparison
path1 = Path('/api/v1')
path2 = Path('/api/v1')
print(path1 == path2) # True
# Boolean evaluation
empty_path = Path()
print(bool(empty_path)) # False
non_empty = Path('/something')
print(bool(non_empty)) # True
# Dictionary representation
path_dict = base_path.asdict()
print(path_dict) # Contains path metadataPaths automatically handle percent-encoding and Unicode characters:
# Unicode characters in paths
unicode_path = Path('/пользователи/123')
print(str(unicode_path)) # Properly encoded
# Percent-encoded input
encoded_path = Path('/users%20with%20spaces')
print(encoded_path.segments) # ['users with spaces'] - automatically decoded
# Special characters
special_path = Path('/special/chars/^`<>[]"#/?')
print(str(special_path)) # '/special/chars/%5E%60%3C%3E%5B%5D%22%23%2F%3F'When a Path is part of a furl object with a netloc (host), certain behaviors change:
from furl import furl
# Path in URL context
f = furl('http://example.com/path')
print(f.path.isabsolute) # True (required for URLs with netloc)
# Attempting to make URL path relative raises error
try:
f.path.isabsolute = False
except AttributeError as e:
print("Cannot make URL path relative when netloc is present")
# Fragment paths don't have this restriction
f.fragment.path.isabsolute = False # This works finePath objects handle various error conditions:
.. and . segments can be normalizedstrict=TrueInstall with Tessl CLI
npx tessl i tessl/pypi-furlevals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
scenario-8
scenario-9
scenario-10