0
# Fragment Handling
1
2
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.
3
4
## Capabilities
5
6
### Fragment Construction and Loading
7
8
Create and load fragment objects from strings with automatic parsing of path and query components.
9
10
```python { .api }
11
class Fragment:
12
def __init__(self, fragment='', strict=False):
13
"""
14
Initialize a Fragment object.
15
16
Args:
17
fragment (str): Fragment string to parse
18
strict (bool): Enable strict parsing mode
19
"""
20
21
def load(self, fragment):
22
"""
23
Load a fragment string into the Fragment object.
24
25
Args:
26
fragment (str): Fragment string to parse
27
28
Returns:
29
Fragment: Self for method chaining
30
"""
31
```
32
33
**Usage:**
34
35
```python
36
from furl import Fragment
37
38
# Create from fragment string with path and query
39
f = Fragment('path/to/section?param=value&other=data')
40
print(f.path.segments) # ['path', 'to', 'section']
41
print(f.query.params['param']) # 'value'
42
43
# Create with just path
44
f = Fragment('simple/path')
45
print(f.path.segments) # ['simple', 'path']
46
print(bool(f.query)) # False
47
48
# Create with just query
49
f = Fragment('?key=value&another=param')
50
print(bool(f.path)) # False
51
print(f.query.params['key']) # 'value'
52
```
53
54
### Fragment Components
55
56
Access and manipulate fragment path and query components independently.
57
58
```python { .api }
59
class Fragment:
60
@property
61
def path(self) -> 'Path':
62
"""
63
Fragment path component (Path object).
64
Independent of main URL path.
65
"""
66
67
@property
68
def query(self) -> 'Query':
69
"""
70
Fragment query component (Query object).
71
Independent of main URL query.
72
"""
73
74
@property
75
def separator(self) -> str | None:
76
"""
77
Separator between fragment path and query.
78
Usually '?' or None if no query.
79
"""
80
81
@separator.setter
82
def separator(self, separator: str | None):
83
"""Set fragment separator"""
84
```
85
86
**Usage:**
87
88
```python
89
f = Fragment('docs/api?version=1&format=json')
90
91
# Access path component
92
print(f.path.segments) # ['docs', 'api']
93
f.path.segments.append('users')
94
print(str(f.path)) # 'docs/api/users'
95
96
# Access query component
97
print(f.query.params['version']) # '1'
98
f.query.add({'limit': '10'})
99
print(str(f.query)) # 'version=1&format=json&limit=10'
100
101
# Check separator
102
print(f.separator) # '?'
103
104
# Modify components independently
105
f.path.set('different/section')
106
f.query.set({'new': 'params'})
107
print(str(f)) # 'different/section?new=params'
108
```
109
110
### Fragment Manipulation
111
112
Add, set, and remove fragment components with method chaining support.
113
114
```python { .api }
115
class Fragment:
116
def add(self, path=None, args=None):
117
"""
118
Add components to the fragment.
119
120
Args:
121
path (str): Path segments to add to fragment path
122
args (dict): Query parameters to add to fragment query
123
124
Returns:
125
Fragment: Self for method chaining
126
"""
127
128
def set(self, path=None, args=None, separator=None):
129
"""
130
Set fragment components, replacing existing values.
131
132
Args:
133
path (str): Path to set for fragment
134
args (dict): Query parameters to set for fragment
135
separator (str): Separator between path and query
136
137
Returns:
138
Fragment: Self for method chaining
139
"""
140
141
def remove(self, fragment=None, path=None, args=None):
142
"""
143
Remove fragment components.
144
145
Args:
146
fragment (bool): Remove entire fragment if True
147
path (str|bool): Path segments to remove or True for all
148
args (list|bool): Query parameter keys to remove or True for all
149
150
Returns:
151
Fragment: Self for method chaining
152
"""
153
```
154
155
**Usage:**
156
157
```python
158
f = Fragment('section1')
159
160
# Add path segments
161
f.add(path='subsection')
162
print(str(f)) # 'section1/subsection'
163
164
# Add query parameters
165
f.add(args={'filter': 'active', 'sort': 'name'})
166
print(str(f)) # 'section1/subsection?filter=active&sort=name'
167
168
# Set new components (replaces existing)
169
f.set(path='newpath', args={'key': 'value'})
170
print(str(f)) # 'newpath?key=value'
171
172
# Remove query parameters
173
f.remove(args=['key'])
174
print(str(f)) # 'newpath'
175
176
# Remove entire fragment
177
f.remove(fragment=True)
178
print(str(f)) # ''
179
```
180
181
### Fragment String Operations
182
183
Convert fragments to strings and perform fragment operations.
184
185
```python { .api }
186
class Fragment:
187
def __str__(self) -> str:
188
"""
189
Convert fragment to string.
190
191
Returns:
192
str: Fragment string with proper encoding
193
"""
194
195
def __eq__(self, other) -> bool:
196
"""Check fragment equality"""
197
198
def __bool__(self) -> bool:
199
"""Boolean evaluation (True if fragment has path or query)"""
200
201
def asdict(self) -> dict:
202
"""
203
Convert fragment to dictionary representation.
204
205
Returns:
206
dict: Dictionary with fragment components
207
"""
208
```
209
210
**Usage:**
211
212
```python
213
f = Fragment('docs/api?version=2')
214
215
# String conversion
216
fragment_str = str(f)
217
print(fragment_str) # 'docs/api?version=2'
218
219
# Fragment comparison
220
f1 = Fragment('path?key=value')
221
f2 = Fragment('path?key=value')
222
print(f1 == f2) # True
223
224
# Boolean evaluation
225
empty_fragment = Fragment()
226
print(bool(empty_fragment)) # False
227
228
non_empty = Fragment('content')
229
print(bool(non_empty)) # True
230
231
# Dictionary representation
232
fragment_dict = f.asdict()
233
print(fragment_dict) # Contains fragment metadata
234
```
235
236
## Advanced Fragment Usage
237
238
### Complex Fragment Paths
239
240
Handle complex path structures within fragments:
241
242
```python
243
f = Fragment()
244
245
# Build complex path
246
f.path.segments = ['documentation', 'api', 'v2', 'authentication']
247
f.path.isabsolute = False # Fragment paths can be relative
248
249
# Add query parameters
250
f.add(args={
251
'section': 'oauth',
252
'example': 'basic',
253
'lang': 'python'
254
})
255
256
print(str(f)) # 'documentation/api/v2/authentication?section=oauth&example=basic&lang=python'
257
```
258
259
### Fragment Query Parameters
260
261
Handle multiple values and complex query structures:
262
263
```python
264
f = Fragment()
265
266
# Multiple values for parameters
267
f.query.params.addlist('tags', ['python', 'url', 'parsing'])
268
f.query.add({'priority': 'high', 'category': 'tutorial'})
269
270
print(str(f)) # '?tags=python&tags=url&tags=parsing&priority=high&category=tutorial'
271
272
# Access specific values
273
print(f.query.params.getlist('tags')) # ['python', 'url', 'parsing']
274
print(f.query.params['priority']) # 'high'
275
```
276
277
### Custom Separators
278
279
Use custom separators between fragment path and query:
280
281
```python
282
f = Fragment('path/to/content?param=value')
283
284
# Change separator
285
f.separator = ';'
286
print(str(f)) # 'path/to/content;param=value'
287
288
# Remove separator (query becomes part of path)
289
f.separator = None
290
# This merges query into path - use carefully
291
292
# Restore standard separator
293
f.separator = '?'
294
```
295
296
### Fragment in URL Context
297
298
Fragments work within furl objects as part of complete URLs:
299
300
```python
301
from furl import furl
302
303
url = furl('https://example.com/page')
304
305
# Set fragment with both path and query
306
url.fragment.set(path='section/overview', args={'highlight': 'introduction'})
307
print(url.url) # 'https://example.com/page#section/overview?highlight=introduction'
308
309
# Add to existing fragment
310
url.fragment.add(path='details')
311
url.fragment.add(args={'expand': 'all'})
312
print(url.url) # 'https://example.com/page#section/overview/details?highlight=introduction&expand=all'
313
314
# Fragment path is independent of main URL path
315
url.path.segments.append('api')
316
print(url.url) # 'https://example.com/page/api#section/overview/details?highlight=introduction&expand=all'
317
```
318
319
## Fragment Encoding
320
321
Fragments handle encoding similarly to paths and queries:
322
323
```python
324
# Unicode in fragment paths
325
f = Fragment('文档/章节')
326
print(str(f)) # Properly encoded
327
328
# Special characters in fragment queries
329
f = Fragment()
330
f.add(args={'search': 'term with spaces & symbols!'})
331
print(str(f)) # '?search=term+with+spaces+%26+symbols%21'
332
333
# Mixed content
334
f = Fragment('path with spaces?key=value with & symbols')
335
print(str(f)) # Properly encoded path and query
336
```
337
338
## Fragment Path vs Main Path
339
340
Fragment paths behave differently from main URL paths:
341
342
```python
343
from furl import furl
344
345
url = furl('https://example.com/main/path')
346
347
# Main path must be absolute when netloc is present
348
print(url.path.isabsolute) # True (read-only)
349
350
# Fragment path can be relative
351
url.fragment.path.segments = ['relative', 'fragment', 'path']
352
url.fragment.path.isabsolute = False
353
print(url.fragment.path.isabsolute) # False (allowed)
354
355
print(url.url) # 'https://example.com/main/path#relative/fragment/path'
356
```
357
358
## Error Handling
359
360
Fragment objects handle various error conditions:
361
362
- **Invalid separators**: Non-standard separators are handled gracefully
363
- **Encoding issues**: Proper percent-encoding/decoding for all components
364
- **Empty components**: Correct handling of fragments with only path or only query
365
- **Unicode support**: Full Unicode support in both path and query components
366
- **Strict mode**: Additional validation when `strict=True`