or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-operations.mdecosystem-utilities.mdframework-integrations.mdindex.mdurl-conversion.md

core-operations.mddocs/

0

# Core PURL Operations

1

2

Essential PackageURL parsing, construction, and manipulation functionality. The core operations provide the fundamental capabilities for working with Package URLs including parsing strings, creating objects, and normalizing components.

3

4

## Capabilities

5

6

### PackageURL Class

7

8

The main class for representing Package URLs with full parsing, validation, and serialization capabilities.

9

10

```python { .api }

11

class PackageURL:

12

"""

13

A Package URL object representing a standardized package identifier.

14

15

Attributes:

16

type (str): Package type (e.g., 'maven', 'npm', 'pypi')

17

namespace (str | None): Package namespace/group

18

name (str): Package name

19

version (str | None): Package version

20

qualifiers (dict[str, str]): Additional qualifiers as key-value pairs

21

subpath (str | None): Subpath within package

22

"""

23

24

def __init__(

25

self,

26

type: str | bytes | None = None,

27

namespace: str | bytes | None = None,

28

name: str | bytes | None = None,

29

version: str | bytes | None = None,

30

qualifiers: str | bytes | dict[str, str] | None = None,

31

subpath: str | bytes | None = None

32

):

33

"""

34

Create a PackageURL object with normalized components.

35

36

Args:

37

type: Package type (required)

38

namespace: Package namespace (optional)

39

name: Package name (required)

40

version: Package version (optional)

41

qualifiers: Qualifiers as dict or string (optional)

42

subpath: Subpath within package (optional)

43

44

Raises:

45

ValueError: If required fields (type, name) are missing or invalid

46

"""

47

48

@classmethod

49

def from_string(cls, purl: str) -> 'PackageURL':

50

"""

51

Parse a PackageURL from a string.

52

53

Args:

54

purl: PURL string to parse

55

56

Returns:

57

PackageURL object

58

59

Raises:

60

ValueError: If purl string is invalid or malformed

61

"""

62

63

def to_string(self, encode: bool = True) -> str:

64

"""

65

Convert PackageURL to string representation.

66

67

Args:

68

encode: Whether to percent-encode components (default: True)

69

70

Returns:

71

PURL string representation

72

"""

73

74

def to_dict(self, encode: bool = False, empty: any = None) -> dict[str, any]:

75

"""

76

Convert PackageURL to dictionary representation.

77

78

Args:

79

encode: Whether to encode qualifiers as string (default: False)

80

empty: Value to use for empty/None fields (default: None)

81

82

Returns:

83

Dictionary with PURL components

84

"""

85

86

def __str__(self) -> str:

87

"""String representation (same as to_string())."""

88

89

def __hash__(self) -> int:

90

"""Hash based on string representation."""

91

92

def _asdict(self) -> dict[str, any]:

93

"""

94

Return PackageURL fields as an ordered dictionary.

95

96

Returns:

97

Ordered dictionary of field names to values

98

"""

99

100

SCHEME: str = "pkg" # PURL scheme constant

101

```

102

103

### Normalization Functions

104

105

Component-wise normalization and validation functions for PackageURL components.

106

107

```python { .api }

108

def normalize(

109

type: str | bytes | None,

110

namespace: str | bytes | None,

111

name: str | bytes | None,

112

version: str | bytes | None,

113

qualifiers: str | bytes | dict[str, str] | None,

114

subpath: str | bytes | None,

115

encode: bool = True

116

) -> tuple[str | None, str | None, str | None, str | None, str | dict[str, str] | None, str | None]:

117

"""

118

Normalize all PackageURL components.

119

120

Args:

121

type: Package type to normalize

122

namespace: Namespace to normalize

123

name: Name to normalize

124

version: Version to normalize

125

qualifiers: Qualifiers to normalize

126

subpath: Subpath to normalize

127

encode: Whether to encode components (default: True)

128

129

Returns:

130

Tuple of normalized components

131

"""

132

133

def normalize_type(type: str | bytes | None, encode: bool = True) -> str | None:

134

"""

135

Normalize package type.

136

137

Args:

138

type: Package type to normalize

139

encode: Whether to percent-encode (default: True)

140

141

Returns:

142

Normalized type string (lowercase, stripped)

143

"""

144

145

def normalize_namespace(

146

namespace: str | bytes | None,

147

ptype: str | None,

148

encode: bool = True

149

) -> str | None:

150

"""

151

Normalize package namespace.

152

153

Args:

154

namespace: Namespace to normalize

155

ptype: Package type (affects normalization rules)

156

encode: Whether to percent-encode (default: True)

157

158

Returns:

159

Normalized namespace string

160

"""

161

162

def normalize_name(

163

name: str | bytes | None,

164

ptype: str | None,

165

encode: bool = True

166

) -> str | None:

167

"""

168

Normalize package name.

169

170

Args:

171

name: Package name to normalize

172

ptype: Package type (affects normalization rules)

173

encode: Whether to percent-encode (default: True)

174

175

Returns:

176

Normalized name string

177

"""

178

179

def normalize_version(version: str | bytes | None, encode: bool = True) -> str | None:

180

"""

181

Normalize package version.

182

183

Args:

184

version: Version to normalize

185

encode: Whether to percent-encode (default: True)

186

187

Returns:

188

Normalized version string

189

"""

190

191

def normalize_qualifiers(

192

qualifiers: str | bytes | dict[str, str] | None,

193

encode: bool = True

194

) -> str | dict[str, str] | None:

195

"""

196

Normalize qualifiers.

197

198

Args:

199

qualifiers: Qualifiers as string or dict

200

encode: Whether to encode as string (True) or return dict (False)

201

202

Returns:

203

Normalized qualifiers as string or dict

204

205

Raises:

206

ValueError: If qualifiers format is invalid

207

"""

208

209

def normalize_subpath(subpath: str | bytes | None, encode: bool = True) -> str | None:

210

"""

211

Normalize subpath.

212

213

Args:

214

subpath: Subpath to normalize

215

encode: Whether to percent-encode (default: True)

216

217

Returns:

218

Normalized subpath string

219

"""

220

```

221

222

### Utility Functions

223

224

Low-level utility functions for encoding and decoding.

225

226

```python { .api }

227

def quote(s: str | bytes) -> str:

228

"""

229

Percent-encode string except for colons.

230

231

Args:

232

s: String or bytes to encode

233

234

Returns:

235

Percent-encoded string

236

"""

237

238

def unquote(s: str | bytes) -> str:

239

"""

240

Percent-decode string.

241

242

Args:

243

s: String or bytes to decode

244

245

Returns:

246

Percent-decoded string

247

"""

248

249

def get_quoter(encode: bool | None = True) -> callable:

250

"""

251

Get appropriate encoding/decoding function.

252

253

Args:

254

encode: True for quote, False for unquote, None for identity

255

256

Returns:

257

Encoding/decoding function

258

"""

259

```

260

261

## Usage Examples

262

263

### Creating PackageURLs

264

265

```python

266

from packageurl import PackageURL

267

268

# Create from components

269

purl = PackageURL(

270

type="maven",

271

namespace="org.apache.commons",

272

name="io",

273

version="1.3.4"

274

)

275

276

# Create with qualifiers

277

purl = PackageURL(

278

type="npm",

279

name="lodash",

280

version="4.17.21",

281

qualifiers={"arch": "x64", "os": "linux"}

282

)

283

```

284

285

### Parsing PURLs

286

287

```python

288

# Parse various PURL formats

289

maven_purl = PackageURL.from_string("pkg:maven/org.springframework/spring-core@5.3.21")

290

npm_purl = PackageURL.from_string("pkg:npm/%40angular/core@12.0.0")

291

pypi_purl = PackageURL.from_string("pkg:pypi/django@3.2.0?extra=security")

292

293

# Access components

294

print(maven_purl.type) # "maven"

295

print(maven_purl.namespace) # "org.springframework"

296

print(maven_purl.name) # "spring-core"

297

print(maven_purl.version) # "5.3.21"

298

```

299

300

### Normalization

301

302

```python

303

from packageurl import normalize, normalize_qualifiers

304

305

# Normalize all components

306

type_n, ns_n, name_n, ver_n, qual_n, sub_n = normalize(

307

"MAVEN",

308

"Org.Apache.Commons",

309

"IO",

310

"1.3.4",

311

"classifier=sources&type=jar",

312

"src/main"

313

)

314

315

# Normalize qualifiers specifically

316

qualifiers_dict = normalize_qualifiers("key1=value1&key2=value2", encode=False)

317

qualifiers_str = normalize_qualifiers({"key1": "value1", "key2": "value2"}, encode=True)

318

```