URL manipulation made simple.
65
The Fragment class manages URL fragments with support for both path and query components within the fragment. It provides flexible fragment manipulation including custom separators and independent path/query handling.
Create and load fragment objects from strings with automatic parsing of path and query components.
class Fragment:
def __init__(self, fragment='', strict=False):
"""
Initialize a Fragment object.
Args:
fragment (str): Fragment string to parse
strict (bool): Enable strict parsing mode
"""
def load(self, fragment):
"""
Load a fragment string into the Fragment object.
Args:
fragment (str): Fragment string to parse
Returns:
Fragment: Self for method chaining
"""Usage:
from furl import Fragment
# Create from fragment string with path and query
f = Fragment('path/to/section?param=value&other=data')
print(f.path.segments) # ['path', 'to', 'section']
print(f.query.params['param']) # 'value'
# Create with just path
f = Fragment('simple/path')
print(f.path.segments) # ['simple', 'path']
print(bool(f.query)) # False
# Create with just query
f = Fragment('?key=value&another=param')
print(bool(f.path)) # False
print(f.query.params['key']) # 'value'Access and manipulate fragment path and query components independently.
class Fragment:
@property
def path(self) -> 'Path':
"""
Fragment path component (Path object).
Independent of main URL path.
"""
@property
def query(self) -> 'Query':
"""
Fragment query component (Query object).
Independent of main URL query.
"""
@property
def separator(self) -> str | None:
"""
Separator between fragment path and query.
Usually '?' or None if no query.
"""
@separator.setter
def separator(self, separator: str | None):
"""Set fragment separator"""Usage:
f = Fragment('docs/api?version=1&format=json')
# Access path component
print(f.path.segments) # ['docs', 'api']
f.path.segments.append('users')
print(str(f.path)) # 'docs/api/users'
# Access query component
print(f.query.params['version']) # '1'
f.query.add({'limit': '10'})
print(str(f.query)) # 'version=1&format=json&limit=10'
# Check separator
print(f.separator) # '?'
# Modify components independently
f.path.set('different/section')
f.query.set({'new': 'params'})
print(str(f)) # 'different/section?new=params'Add, set, and remove fragment components with method chaining support.
class Fragment:
def add(self, path=None, args=None):
"""
Add components to the fragment.
Args:
path (str): Path segments to add to fragment path
args (dict): Query parameters to add to fragment query
Returns:
Fragment: Self for method chaining
"""
def set(self, path=None, args=None, separator=None):
"""
Set fragment components, replacing existing values.
Args:
path (str): Path to set for fragment
args (dict): Query parameters to set for fragment
separator (str): Separator between path and query
Returns:
Fragment: Self for method chaining
"""
def remove(self, fragment=None, path=None, args=None):
"""
Remove fragment components.
Args:
fragment (bool): Remove entire fragment if True
path (str|bool): Path segments to remove or True for all
args (list|bool): Query parameter keys to remove or True for all
Returns:
Fragment: Self for method chaining
"""Usage:
f = Fragment('section1')
# Add path segments
f.add(path='subsection')
print(str(f)) # 'section1/subsection'
# Add query parameters
f.add(args={'filter': 'active', 'sort': 'name'})
print(str(f)) # 'section1/subsection?filter=active&sort=name'
# Set new components (replaces existing)
f.set(path='newpath', args={'key': 'value'})
print(str(f)) # 'newpath?key=value'
# Remove query parameters
f.remove(args=['key'])
print(str(f)) # 'newpath'
# Remove entire fragment
f.remove(fragment=True)
print(str(f)) # ''Convert fragments to strings and perform fragment operations.
class Fragment:
def __str__(self) -> str:
"""
Convert fragment to string.
Returns:
str: Fragment string with proper encoding
"""
def __eq__(self, other) -> bool:
"""Check fragment equality"""
def __bool__(self) -> bool:
"""Boolean evaluation (True if fragment has path or query)"""
def asdict(self) -> dict:
"""
Convert fragment to dictionary representation.
Returns:
dict: Dictionary with fragment components
"""Usage:
f = Fragment('docs/api?version=2')
# String conversion
fragment_str = str(f)
print(fragment_str) # 'docs/api?version=2'
# Fragment comparison
f1 = Fragment('path?key=value')
f2 = Fragment('path?key=value')
print(f1 == f2) # True
# Boolean evaluation
empty_fragment = Fragment()
print(bool(empty_fragment)) # False
non_empty = Fragment('content')
print(bool(non_empty)) # True
# Dictionary representation
fragment_dict = f.asdict()
print(fragment_dict) # Contains fragment metadataHandle complex path structures within fragments:
f = Fragment()
# Build complex path
f.path.segments = ['documentation', 'api', 'v2', 'authentication']
f.path.isabsolute = False # Fragment paths can be relative
# Add query parameters
f.add(args={
'section': 'oauth',
'example': 'basic',
'lang': 'python'
})
print(str(f)) # 'documentation/api/v2/authentication?section=oauth&example=basic&lang=python'Handle multiple values and complex query structures:
f = Fragment()
# Multiple values for parameters
f.query.params.addlist('tags', ['python', 'url', 'parsing'])
f.query.add({'priority': 'high', 'category': 'tutorial'})
print(str(f)) # '?tags=python&tags=url&tags=parsing&priority=high&category=tutorial'
# Access specific values
print(f.query.params.getlist('tags')) # ['python', 'url', 'parsing']
print(f.query.params['priority']) # 'high'Use custom separators between fragment path and query:
f = Fragment('path/to/content?param=value')
# Change separator
f.separator = ';'
print(str(f)) # 'path/to/content;param=value'
# Remove separator (query becomes part of path)
f.separator = None
# This merges query into path - use carefully
# Restore standard separator
f.separator = '?'Fragments work within furl objects as part of complete URLs:
from furl import furl
url = furl('https://example.com/page')
# Set fragment with both path and query
url.fragment.set(path='section/overview', args={'highlight': 'introduction'})
print(url.url) # 'https://example.com/page#section/overview?highlight=introduction'
# Add to existing fragment
url.fragment.add(path='details')
url.fragment.add(args={'expand': 'all'})
print(url.url) # 'https://example.com/page#section/overview/details?highlight=introduction&expand=all'
# Fragment path is independent of main URL path
url.path.segments.append('api')
print(url.url) # 'https://example.com/page/api#section/overview/details?highlight=introduction&expand=all'Fragments handle encoding similarly to paths and queries:
# Unicode in fragment paths
f = Fragment('文档/章节')
print(str(f)) # Properly encoded
# Special characters in fragment queries
f = Fragment()
f.add(args={'search': 'term with spaces & symbols!'})
print(str(f)) # '?search=term+with+spaces+%26+symbols%21'
# Mixed content
f = Fragment('path with spaces?key=value with & symbols')
print(str(f)) # Properly encoded path and queryFragment paths behave differently from main URL paths:
from furl import furl
url = furl('https://example.com/main/path')
# Main path must be absolute when netloc is present
print(url.path.isabsolute) # True (read-only)
# Fragment path can be relative
url.fragment.path.segments = ['relative', 'fragment', 'path']
url.fragment.path.isabsolute = False
print(url.fragment.path.isabsolute) # False (allowed)
print(url.url) # 'https://example.com/main/path#relative/fragment/path'Fragment objects handle various error conditions:
strict=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