or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cli.mdindex.mdmodels.mdparsing.mdspdx3.mdvalidation.mdwriting.md

cli.mddocs/

0

# Command Line Tools

1

2

CLI tools for parsing, validating, converting, and analyzing SPDX documents with support for all major formats and comprehensive error reporting.

3

4

## Capabilities

5

6

### Main CLI Tool (pyspdxtools)

7

8

Primary command-line interface for SPDX document operations including validation, conversion, and relationship graph generation.

9

10

```python { .api }

11

def main(infile: str, outfile: str, version: str, novalidation: bool, graph: bool):

12

"""

13

CLI entry point for pyspdxtools command.

14

15

Provides comprehensive SPDX document processing including:

16

- Parsing documents in any supported format

17

- Validating against SPDX specifications

18

- Converting between formats

19

- Generating relationship graphs

20

21

Args:

22

infile: Input SPDX file path (required)

23

outfile: Output file path (optional, "-" for stdout)

24

version: SPDX version to validate against ("SPDX-2.2" or "SPDX-2.3")

25

novalidation: Skip validation if True

26

graph: Generate relationship graph if True (requires networkx, pygraphviz)

27

28

Exit Codes:

29

0: Success

30

1: Validation or processing error

31

"""

32

```

33

34

### SPDX 3.0 CLI Tool (pyspdxtools3)

35

36

Experimental command-line interface for SPDX 3.0 document operations.

37

38

```python { .api }

39

def main() -> None:

40

"""

41

CLI entry point for pyspdxtools3 command.

42

43

Experimental CLI for SPDX 3.0 document processing.

44

Functionality and API subject to change.

45

"""

46

```

47

48

### Graph Generation

49

50

Generate visual relationship graphs from SPDX documents.

51

52

```python { .api }

53

def export_graph_from_document(document: Document, output_file: str) -> None:

54

"""

55

Generate relationship graph visualization from SPDX document.

56

57

Creates graphical representation of SPDX relationships showing

58

connections between packages, files, and other elements.

59

60

Args:

61

document: SPDX document to visualize

62

output_file: Output file path for graph image

63

64

Raises:

65

ImportError: If networkx or pygraphviz not installed

66

67

Note:

68

Requires optional dependencies: pip install "spdx-tools[graph_generation]"

69

"""

70

```

71

72

## Usage Examples

73

74

### Basic Command Line Usage

75

76

```bash

77

# Validate SPDX document

78

pyspdxtools --infile document.spdx

79

80

# Convert between formats

81

pyspdxtools --infile document.spdx --outfile document.json

82

83

# Skip validation for faster conversion

84

pyspdxtools --infile document.spdx --outfile document.json --novalidation

85

86

# Validate against specific SPDX version

87

pyspdxtools --infile document.spdx --version SPDX-2.3

88

89

# Output to stdout (Tag-Value format)

90

pyspdxtools --infile document.json --outfile -

91

92

# Generate relationship graph

93

pyspdxtools --infile document.spdx --outfile relationships.png --graph

94

```

95

96

### Programmatic CLI Usage

97

98

```python

99

import sys

100

from spdx_tools.spdx.clitools.pyspdxtools import main

101

102

# Simulate command line arguments

103

sys.argv = [

104

"pyspdxtools",

105

"--infile", "input.spdx",

106

"--outfile", "output.json",

107

"--version", "SPDX-2.3"

108

]

109

110

try:

111

main()

112

print("CLI operation completed successfully")

113

except SystemExit as e:

114

if e.code == 0:

115

print("Success")

116

else:

117

print(f"Failed with exit code: {e.code}")

118

```

119

120

### Batch Processing Script

121

122

```python

123

import os

124

import subprocess

125

import sys

126

from pathlib import Path

127

128

def process_spdx_files(input_dir: str, output_dir: str, target_format: str):

129

"""Process all SPDX files in directory using CLI tool."""

130

input_path = Path(input_dir)

131

output_path = Path(output_dir)

132

output_path.mkdir(exist_ok=True)

133

134

# Find all SPDX files

135

spdx_files = []

136

for ext in [".spdx", ".json", ".yaml", ".xml", ".rdf"]:

137

spdx_files.extend(input_path.glob(f"*{ext}"))

138

139

for input_file in spdx_files:

140

output_file = output_path / f"{input_file.stem}.{target_format}"

141

142

# Run pyspdxtools via subprocess

143

cmd = [

144

"pyspdxtools",

145

"--infile", str(input_file),

146

"--outfile", str(output_file)

147

]

148

149

try:

150

result = subprocess.run(cmd, capture_output=True, text=True)

151

if result.returncode == 0:

152

print(f"✅ Converted {input_file.name} -> {output_file.name}")

153

else:

154

print(f"❌ Failed to convert {input_file.name}")

155

print(f" Error: {result.stderr}")

156

except Exception as e:

157

print(f"❌ Error processing {input_file.name}: {e}")

158

159

# Usage

160

process_spdx_files("input_documents/", "output_documents/", "json")

161

```

162

163

### Validation Pipeline

164

165

```python

166

import subprocess

167

import json

168

from pathlib import Path

169

170

def validate_spdx_collection(directory: str) -> dict:

171

"""Validate all SPDX files in directory and return results."""

172

results = {

173

"total_files": 0,

174

"valid_files": 0,

175

"invalid_files": 0,

176

"errors": []

177

}

178

179

spdx_files = []

180

for ext in [".spdx", ".json", ".yaml", ".xml", ".rdf"]:

181

spdx_files.extend(Path(directory).glob(f"*{ext}"))

182

183

results["total_files"] = len(spdx_files)

184

185

for spdx_file in spdx_files:

186

cmd = ["pyspdxtools", "--infile", str(spdx_file)]

187

188

try:

189

result = subprocess.run(cmd, capture_output=True, text=True)

190

if result.returncode == 0:

191

results["valid_files"] += 1

192

print(f"✅ {spdx_file.name} is valid")

193

else:

194

results["invalid_files"] += 1

195

results["errors"].append({

196

"file": spdx_file.name,

197

"error": result.stderr.strip()

198

})

199

print(f"❌ {spdx_file.name} is invalid")

200

except Exception as e:

201

results["invalid_files"] += 1

202

results["errors"].append({

203

"file": spdx_file.name,

204

"error": str(e)

205

})

206

print(f"❌ Error validating {spdx_file.name}: {e}")

207

208

return results

209

210

# Generate validation report

211

results = validate_spdx_collection("spdx_documents/")

212

print(f"\nValidation Summary:")

213

print(f"Total files: {results['total_files']}")

214

print(f"Valid files: {results['valid_files']}")

215

print(f"Invalid files: {results['invalid_files']}")

216

217

# Save detailed report

218

with open("validation_report.json", "w") as f:

219

json.dump(results, f, indent=2)

220

```

221

222

### Graph Generation Examples

223

224

```bash

225

# Generate relationship graph

226

pyspdxtools --infile complex_project.spdx --outfile project_graph.png --graph

227

228

# Generate graph with specific format conversion

229

pyspdxtools --infile document.json --outfile graph.svg --graph

230

```

231

232

### CI/CD Integration

233

234

```yaml

235

# GitHub Actions example

236

name: SPDX Validation

237

on: [push, pull_request]

238

239

jobs:

240

validate-spdx:

241

runs-on: ubuntu-latest

242

steps:

243

- uses: actions/checkout@v3

244

- name: Set up Python

245

uses: actions/setup-python@v3

246

with:

247

python-version: '3.9'

248

- name: Install spdx-tools

249

run: pip install spdx-tools

250

- name: Validate SPDX documents

251

run: |

252

for file in *.spdx *.json; do

253

if [ -f "$file" ]; then

254

echo "Validating $file..."

255

pyspdxtools --infile "$file" || exit 1

256

fi

257

done

258

- name: Convert to JSON for artifacts

259

run: |

260

for file in *.spdx; do

261

if [ -f "$file" ]; then

262

pyspdxtools --infile "$file" --outfile "${file%.*}.json"

263

fi

264

done

265

```

266

267

### Docker Usage

268

269

```dockerfile

270

FROM python:3.9-slim

271

272

RUN pip install spdx-tools[graph_generation]

273

274

# Copy SPDX documents

275

COPY *.spdx /app/

276

WORKDIR /app

277

278

# Validate and convert documents

279

RUN for file in *.spdx; do \

280

pyspdxtools --infile "$file" --outfile "${file%.*}.json"; \

281

done

282

283

# Generate graphs

284

RUN for file in *.spdx; do \

285

pyspdxtools --infile "$file" --outfile "${file%.*}_graph.png" --graph; \

286

done

287

```

288

289

### Error Handling Patterns

290

291

```python

292

import subprocess

293

import logging

294

295

def safe_spdx_operation(input_file: str, output_file: str = None,

296

validate: bool = True, graph: bool = False) -> bool:

297

"""Safely perform SPDX operations with comprehensive error handling."""

298

299

cmd = ["pyspdxtools", "--infile", input_file]

300

301

if output_file:

302

cmd.extend(["--outfile", output_file])

303

304

if not validate:

305

cmd.append("--novalidation")

306

307

if graph:

308

cmd.append("--graph")

309

310

try:

311

result = subprocess.run(cmd, capture_output=True, text=True, timeout=300)

312

313

if result.returncode == 0:

314

logging.info(f"Successfully processed {input_file}")

315

if result.stdout:

316

logging.info(f"Output: {result.stdout}")

317

return True

318

else:

319

logging.error(f"Failed to process {input_file}")

320

logging.error(f"Error output: {result.stderr}")

321

return False

322

323

except subprocess.TimeoutExpired:

324

logging.error(f"Timeout processing {input_file}")

325

return False

326

except FileNotFoundError:

327

logging.error("pyspdxtools command not found. Is spdx-tools installed?")

328

return False

329

except Exception as e:

330

logging.error(f"Unexpected error processing {input_file}: {e}")

331

return False

332

333

# Usage

334

success = safe_spdx_operation("document.spdx", "document.json")

335

if success:

336

print("Operation completed successfully")

337

else:

338

print("Operation failed")

339

```

340

341

## Types

342

343

```python { .api }

344

from typing import Optional

345

346

# CLI functions work with file paths and configuration options

347

# Return values are typically None (success) or sys.exit() calls

348

```