or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cache-management.mdcore-url.mdindex.mdpath-operations.mdquery-handling.mdurl-modification.md

path-operations.mddocs/

0

# Path Operations

1

2

Path manipulation, normalization, and joining operations for URL path components, including filename and extension handling with support for complex path manipulations.

3

4

## Capabilities

5

6

### Path Construction and Joining

7

8

Methods for building and extending URL paths with proper encoding and normalization.

9

10

```python { .api }

11

def joinpath(self, *other: str, encoded: bool = False) -> "URL":

12

"""

13

Join URL path with additional path segments.

14

15

Args:

16

*other (str): Path segments to append

17

encoded (bool): Whether path segments are already encoded

18

19

Returns:

20

URL: New URL with joined path segments

21

22

Examples:

23

url.joinpath('api', 'v1', 'users')

24

url.joinpath('files', 'document.pdf')

25

url.joinpath('path with spaces', encoded=False)

26

"""

27

28

def join(self, url: "URL") -> "URL":

29

"""

30

Join this URL with another URL using RFC 3986 resolution rules.

31

32

Args:

33

url (URL): URL to resolve against this URL

34

35

Returns:

36

URL: New URL after RFC 3986 resolution

37

38

Examples:

39

base.join(URL('path/to/resource'))

40

base.join(URL('../parent/resource'))

41

base.join(URL('?query=value'))

42

"""

43

44

def __truediv__(self, name: str) -> "URL":

45

"""

46

Append path segment using / operator.

47

48

Args:

49

name (str): Path segment to append

50

51

Returns:

52

URL: New URL with appended path segment

53

54

Examples:

55

url / 'api' / 'v1' / 'users'

56

url / 'documents' / 'file.pdf'

57

"""

58

```

59

60

### Path Component Access

61

62

Properties for accessing path components and segments.

63

64

```python { .api }

65

@property

66

def raw_parts(self) -> tuple[str, ...]:

67

"""

68

Raw path segments as tuple.

69

70

Returns:

71

tuple[str, ...]: Tuple of raw (encoded) path segments

72

73

Examples:

74

URL('/path/to/file').raw_parts # ('/', 'path', 'to', 'file')

75

URL('/api/v1/').raw_parts # ('/', 'api', 'v1', '')

76

"""

77

78

@property

79

def parts(self) -> tuple[str, ...]:

80

"""

81

Decoded path segments as tuple.

82

83

Returns:

84

tuple[str, ...]: Tuple of decoded path segments

85

"""

86

87

@property

88

def parent(self) -> "URL":

89

"""

90

Parent URL (removes last path segment).

91

92

Returns:

93

URL: New URL with last path segment removed

94

95

Examples:

96

URL('/path/to/file').parent # URL('/path/to')

97

URL('/api/v1/users').parent # URL('/api/v1')

98

URL('/').parent # URL('/')

99

"""

100

101

@property

102

def raw_path(self) -> str:

103

"""Raw (encoded) path component"""

104

105

@property

106

def path(self) -> str:

107

"""Decoded path component"""

108

109

@property

110

def path_safe(self) -> str:

111

"""Path with safe decoding (preserves important characters like /)"""

112

```

113

114

### Filename and Extension Operations

115

116

Methods and properties for working with filename components of paths.

117

118

```python { .api }

119

@property

120

def raw_name(self) -> str:

121

"""

122

Raw filename component (last path segment).

123

124

Returns:

125

str: Raw filename or empty string if path ends with /

126

"""

127

128

@property

129

def name(self) -> str:

130

"""

131

Decoded filename component (last path segment).

132

133

Returns:

134

str: Decoded filename or empty string if path ends with /

135

136

Examples:

137

URL('/documents/report.pdf').name # 'report.pdf'

138

URL('/api/users/').name # ''

139

URL('/path/to/file').name # 'file'

140

"""

141

142

@property

143

def raw_suffix(self) -> str:

144

"""

145

Raw file extension including leading dot.

146

147

Returns:

148

str: Raw file extension or empty string if no extension

149

"""

150

151

@property

152

def suffix(self) -> str:

153

"""

154

Decoded file extension including leading dot.

155

156

Returns:

157

str: Decoded file extension or empty string if no extension

158

159

Examples:

160

URL('/file.txt').suffix # '.txt'

161

URL('/archive.tar.gz').suffix # '.gz'

162

URL('/README').suffix # ''

163

"""

164

165

@property

166

def raw_suffixes(self) -> tuple[str, ...]:

167

"""

168

All raw file extensions as tuple.

169

170

Returns:

171

tuple[str, ...]: Tuple of all raw extensions

172

"""

173

174

@property

175

def suffixes(self) -> tuple[str, ...]:

176

"""

177

All decoded file extensions as tuple.

178

179

Returns:

180

tuple[str, ...]: Tuple of all decoded extensions

181

182

Examples:

183

URL('/file.txt').suffixes # ('.txt',)

184

URL('/archive.tar.gz').suffixes # ('.tar', '.gz')

185

URL('/document.backup.old').suffixes # ('.backup', '.old')

186

"""

187

188

def with_name(self, name: str, *, encoded: bool = False) -> "URL":

189

"""

190

Return URL with new filename component.

191

192

Args:

193

name (str): New filename to replace current filename

194

encoded (bool): Whether name is already encoded

195

196

Returns:

197

URL: New URL with updated filename

198

199

Raises:

200

ValueError: If name contains path separators

201

202

Examples:

203

url.with_name('newfile.txt')

204

url.with_name('document with spaces.pdf')

205

"""

206

207

def with_suffix(self, suffix: str, *, encoded: bool = False) -> "URL":

208

"""

209

Return URL with new file extension.

210

211

Args:

212

suffix (str): New file extension (should include leading dot)

213

encoded (bool): Whether suffix is already encoded

214

215

Returns:

216

URL: New URL with updated file extension

217

218

Examples:

219

url.with_suffix('.json')

220

url.with_suffix('.backup.txt')

221

"""

222

```

223

224

### Path Normalization

225

226

Built-in path normalization handles relative path components and ensures clean paths.

227

228

Path normalization automatically:

229

- Resolves `.` (current directory) references

230

- Resolves `..` (parent directory) references

231

- Removes duplicate slashes

232

- Preserves trailing slashes when semantically significant

233

234

## Usage Examples

235

236

### Basic Path Operations

237

238

```python

239

from yarl import URL

240

241

base_url = URL('https://example.com/api/v1')

242

243

# Append path segments

244

users_url = base_url.joinpath('users')

245

print(users_url) # https://example.com/api/v1/users

246

247

user_url = base_url.joinpath('users', '123')

248

print(user_url) # https://example.com/api/v1/users/123

249

250

# Multiple segments at once

251

deep_url = base_url.joinpath('resources', 'documents', 'files')

252

print(deep_url) # https://example.com/api/v1/resources/documents/files

253

```

254

255

### Using the / Operator

256

257

```python

258

from yarl import URL

259

260

api_url = URL('https://api.example.com')

261

262

# Chain path segments

263

endpoint = api_url / 'v2' / 'users' / '456' / 'profile'

264

print(endpoint) # https://api.example.com/v2/users/456/profile

265

266

# Mix with other operations

267

full_url = (api_url

268

/ 'search'

269

/ 'documents'

270

% {'q': 'python', 'limit': 10})

271

print(full_url) # https://api.example.com/search/documents?q=python&limit=10

272

```

273

274

### Working with Filenames

275

276

```python

277

from yarl import URL

278

279

file_url = URL('https://cdn.example.com/documents/report.pdf')

280

281

# Access filename components

282

print(file_url.name) # 'report.pdf'

283

print(file_url.suffix) # '.pdf'

284

print(file_url.suffixes) # ('.pdf',)

285

286

# Modify filename

287

new_file = file_url.with_name('summary.pdf')

288

print(new_file) # https://cdn.example.com/documents/summary.pdf

289

290

# Change extension

291

txt_version = file_url.with_suffix('.txt')

292

print(txt_version) # https://cdn.example.com/documents/report.txt

293

294

# Work with parent directories

295

parent = file_url.parent

296

print(parent) # https://cdn.example.com/documents

297

298

grandparent = file_url.parent.parent

299

print(grandparent) # https://cdn.example.com

300

```

301

302

### Complex File Extensions

303

304

```python

305

from yarl import URL

306

307

archive_url = URL('https://example.com/files/backup.tar.gz')

308

309

print(archive_url.suffix) # '.gz' (last extension)

310

print(archive_url.suffixes) # ('.tar', '.gz') (all extensions)

311

312

# Change just the compression

313

uncompressed = archive_url.with_suffix('.tar')

314

print(uncompressed) # https://example.com/files/backup.tar

315

316

# Multiple extensions

317

config_url = URL('https://example.com/config.local.dev.json')

318

print(config_url.suffixes) # ('.local', '.dev', '.json')

319

320

# Remove all extensions by changing name

321

base_name = config_url.name.split('.')[0] # 'config'

322

clean_url = config_url.with_name(base_name)

323

print(clean_url) # https://example.com/config

324

```

325

326

### Path Segments and Navigation

327

328

```python

329

from yarl import URL

330

331

deep_url = URL('https://example.com/api/v1/users/123/documents/456')

332

333

# Access path segments

334

print(deep_url.parts) # ('/', 'api', 'v1', 'users', '123', 'documents', '456')

335

336

# Navigate up the hierarchy

337

print(deep_url.parent) # https://example.com/api/v1/users/123/documents

338

print(deep_url.parent.parent) # https://example.com/api/v1/users/123

339

print(deep_url.parent.parent.parent) # https://example.com/api/v1/users

340

341

# Build new paths from segments

342

segments = deep_url.parts[1:4] # ('api', 'v1', 'users')

343

new_base = URL('https://example.com').joinpath(*segments)

344

print(new_base) # https://example.com/api/v1/users

345

```

346

347

### Path Normalization Examples

348

349

```python

350

from yarl import URL

351

352

# Relative path resolution

353

messy_url = URL('https://example.com/api/../docs/./guide/../tutorial/basics.html')

354

print(messy_url) # Automatically normalized to: https://example.com/docs/tutorial/basics.html

355

356

# Join with relative paths

357

base = URL('https://example.com/api/v1/users')

358

relative_join = base.join(URL('../docs/guide.html'))

359

print(relative_join) # https://example.com/api/v1/docs/guide.html

360

361

# Complex relative navigation

362

complex_base = URL('https://example.com/app/module/submodule/')

363

back_and_forward = complex_base.join(URL('../../other/module/file.js'))

364

print(back_and_forward) # https://example.com/app/other/module/file.js

365

```

366

367

### URL Resolution (RFC 3986)

368

369

```python

370

from yarl import URL

371

372

base_url = URL('https://example.com/app/current/page')

373

374

# Absolute URL resolution

375

absolute_result = base_url.join(URL('https://other.com/resource'))

376

print(absolute_result) # https://other.com/resource

377

378

# Relative path resolution

379

relative_result = base_url.join(URL('other/resource'))

380

print(relative_result) # https://example.com/app/current/other/resource

381

382

# Parent directory resolution

383

parent_result = base_url.join(URL('../sibling/resource'))

384

print(parent_result) # https://example.com/app/sibling/resource

385

386

# Query-only resolution

387

query_result = base_url.join(URL('?query=value'))

388

print(query_result) # https://example.com/app/current/page?query=value

389

390

# Fragment-only resolution

391

fragment_result = base_url.join(URL('#section'))

392

print(fragment_result) # https://example.com/app/current/page#section

393

```

394

395

### Special Path Cases

396

397

```python

398

from yarl import URL

399

400

# Root path operations

401

root_url = URL('https://example.com/')

402

api_from_root = root_url / 'api' / 'v1'

403

print(api_from_root) # https://example.com/api/v1

404

405

# Empty path components

406

empty_url = URL('https://example.com')

407

with_empty = empty_url.joinpath('', 'api', '', 'users')

408

print(with_empty) # https://example.com/api/users (empty segments ignored)

409

410

# Trailing slash preservation

411

trailing_url = URL('https://example.com/api/')

412

print(trailing_url.joinpath('users')) # https://example.com/api/users

413

print(trailing_url / 'users') # https://example.com/api/users

414

415

# Special characters in paths

416

special_url = URL('https://example.com').joinpath('files', 'my document.pdf')

417

print(special_url) # https://example.com/files/my%20document.pdf (automatically encoded)

418

```