or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

built-in-checkers.mdchecker-development.mdconfiguration.mdcore-linting.mdextensions.mdindex.mdmessages.mdpyreverse.mdreporters.mdtest-utilities.md

reporters.mddocs/

0

# Reporters and Output

1

2

Flexible reporting system supporting multiple output formats and custom reporter development. Pylint's reporter architecture allows integration with different tools, IDEs, and continuous integration systems through standardized and custom output formats.

3

4

## Capabilities

5

6

### Base Reporter System

7

8

Foundation classes for all reporters providing the interface and common functionality.

9

10

```python { .api }

11

class BaseReporter:

12

"""

13

Abstract base class for all reporters.

14

15

Attributes:

16

out: Output stream for writing results

17

messages: List of collected messages

18

path_strip_prefix: Prefix to strip from file paths

19

"""

20

21

def __init__(self, output=None):

22

"""

23

Initialize the reporter.

24

25

Args:

26

output: Output stream (default: sys.stdout)

27

"""

28

29

def handle_message(self, msg):

30

"""

31

Handle a single message.

32

33

Args:

34

msg: Message instance to process

35

"""

36

37

def display_messages(self, layout):

38

"""

39

Display messages after collection.

40

41

Args:

42

layout: Layout object for organizing output (can be None)

43

"""

44

45

def writeln(self, string=''):

46

"""

47

Write a line to output.

48

49

Args:

50

string: String to write (default: empty line)

51

"""

52

53

def display_reports(self, layout):

54

"""

55

Display analysis reports.

56

57

Args:

58

layout: Report layout object

59

"""

60

61

def on_set_current_module(self, module, filepath):

62

"""

63

Called when switching to a new module.

64

65

Args:

66

module: Module name

67

filepath: Path to the module file

68

"""

69

```

70

71

### Built-in Reporters

72

73

Standard reporters for common output formats and use cases.

74

75

```python { .api }

76

class TextReporter(BaseReporter):

77

"""

78

Default text output reporter.

79

80

Outputs messages in human-readable format with file paths,

81

line numbers, message types, and descriptions.

82

"""

83

84

name = 'text'

85

extension = 'txt'

86

87

class ColorizedTextReporter(TextReporter):

88

"""

89

Text reporter with color output for terminals.

90

91

Adds ANSI color codes to highlight different message types

92

and improve readability in terminal environments.

93

"""

94

95

name = 'colorized'

96

97

class JSONReporter(BaseReporter):

98

"""

99

JSON format reporter for programmatic consumption.

100

101

Outputs messages as JSON array with structured data

102

suitable for parsing by other tools and scripts.

103

"""

104

105

name = 'json'

106

extension = 'json'

107

108

class JSON2Reporter(BaseReporter):

109

"""

110

Enhanced JSON reporter with additional metadata.

111

112

Includes extended message information, statistics,

113

and analysis metadata in JSON format.

114

"""

115

116

name = 'json2'

117

extension = 'json'

118

```

119

120

### Specialized Reporters

121

122

Reporters for specific use cases and integrations.

123

124

```python { .api }

125

class CollectingReporter(BaseReporter):

126

"""

127

Reporter that collects messages in memory.

128

129

Useful for programmatic access to analysis results

130

without writing to files or streams.

131

"""

132

133

name = 'collector'

134

135

def finalize(self):

136

"""

137

Finalize collection and return messages.

138

139

Returns:

140

list: Collected messages

141

"""

142

143

class MultiReporter(BaseReporter):

144

"""

145

Reporter that delegates to multiple sub-reporters.

146

147

Allows simultaneous output to multiple formats

148

(e.g., console display and file logging).

149

"""

150

151

def __init__(self, reporters):

152

"""

153

Initialize with multiple reporters.

154

155

Args:

156

reporters: List of reporter instances

157

"""

158

159

def add_reporter(self, reporter):

160

"""

161

Add a new reporter to the collection.

162

163

Args:

164

reporter: Reporter instance to add

165

"""

166

```

167

168

### Report Generation System

169

170

Mixin class providing report generation capabilities.

171

172

```python { .api }

173

class ReportsHandlerMixIn:

174

"""

175

Mixin providing report generation utilities.

176

177

Handles statistics collection, report formatting,

178

and output generation for analysis results.

179

"""

180

181

def add_stats(self, **kwargs):

182

"""

183

Add statistics to the report.

184

185

Args:

186

**kwargs: Statistics key-value pairs

187

"""

188

189

def make_reports(self, stats, old_stats):

190

"""

191

Generate analysis reports.

192

193

Args:

194

stats: Current analysis statistics

195

old_stats: Previous analysis statistics for comparison

196

"""

197

198

def generate_reports(self):

199

"""Generate and display all reports."""

200

```

201

202

### Custom Reporter Development

203

204

Framework for creating custom reporters for specific output formats or integrations.

205

206

```python { .api }

207

# Custom reporter pattern

208

class CustomReporter(BaseReporter):

209

"""Template for custom reporter implementation."""

210

211

name = 'custom' # Unique name for the reporter

212

extension = 'ext' # File extension for output

213

214

def __init__(self, output=None):

215

"""Initialize custom reporter."""

216

super().__init__(output)

217

self.custom_data = {}

218

219

def handle_message(self, msg):

220

"""Process each message according to custom format."""

221

# Custom message processing logic

222

formatted_msg = self.format_message(msg)

223

self.writeln(formatted_msg)

224

225

def format_message(self, msg):

226

"""Format message according to custom requirements."""

227

return f"Custom: {msg.path}:{msg.line} - {msg.msg}"

228

229

def display_reports(self, layout):

230

"""Generate custom report format."""

231

# Custom report generation logic

232

pass

233

```

234

235

## Usage Examples

236

237

### Using Built-in Reporters

238

239

```python

240

from pylint.lint import PyLinter

241

from pylint.reporters import TextReporter, JSONReporter

242

import sys

243

244

# Text reporter to stdout

245

linter = PyLinter()

246

text_reporter = TextReporter(sys.stdout)

247

linter.set_reporter(text_reporter)

248

linter.check(['mymodule.py'])

249

250

# JSON reporter to file

251

with open('pylint_results.json', 'w') as f:

252

json_reporter = JSONReporter(f)

253

linter.set_reporter(json_reporter)

254

linter.check(['mymodule.py'])

255

256

# Collecting reporter for programmatic access

257

from pylint.reporters import CollectingReporter

258

collector = CollectingReporter()

259

linter.set_reporter(collector)

260

linter.check(['mymodule.py'])

261

messages = collector.finalize()

262

for msg in messages:

263

print(f"{msg.msg_id}: {msg.msg}")

264

```

265

266

### Multiple Output Formats

267

268

```python

269

from pylint.reporters import MultiReporter, TextReporter, JSONReporter

270

import sys

271

272

# Output to both console and JSON file

273

text_reporter = TextReporter(sys.stdout)

274

with open('results.json', 'w') as f:

275

json_reporter = JSONReporter(f)

276

multi_reporter = MultiReporter([text_reporter, json_reporter])

277

278

linter = PyLinter()

279

linter.set_reporter(multi_reporter)

280

linter.check(['mymodule.py'])

281

```

282

283

### Custom Reporter Implementation

284

285

```python

286

from pylint.reporters import BaseReporter

287

import xml.etree.ElementTree as ET

288

289

class XMLReporter(BaseReporter):

290

"""Custom XML reporter for test result integration."""

291

292

name = 'xml'

293

extension = 'xml'

294

295

def __init__(self, output=None):

296

super().__init__(output)

297

self.root = ET.Element('pylint-results')

298

self.current_file = None

299

300

def on_set_current_module(self, module, filepath):

301

"""Create XML element for new module."""

302

self.current_file = ET.SubElement(self.root, 'file')

303

self.current_file.set('name', filepath)

304

305

def handle_message(self, msg):

306

"""Add message as XML element."""

307

if self.current_file is not None:

308

issue = ET.SubElement(self.current_file, 'issue')

309

issue.set('line', str(msg.line))

310

issue.set('column', str(msg.column))

311

issue.set('severity', msg.category)

312

issue.set('message', msg.msg)

313

issue.set('message-id', msg.msg_id)

314

315

def display_reports(self, layout):

316

"""Output final XML."""

317

tree = ET.ElementTree(self.root)

318

tree.write(self.out, encoding='unicode', xml_declaration=True)

319

320

# Register and use custom reporter

321

def register_reporter(reporter_class):

322

"""Register custom reporter with pylint."""

323

# Registration logic would go here

324

pass

325

326

register_reporter(XMLReporter)

327

```

328

329

### IDE Integration Reporter

330

331

```python

332

class IDEReporter(BaseReporter):

333

"""Reporter optimized for IDE integration."""

334

335

name = 'ide'

336

337

def __init__(self, output=None):

338

super().__init__(output)

339

self.messages_by_file = {}

340

341

def handle_message(self, msg):

342

"""Group messages by file for IDE consumption."""

343

if msg.path not in self.messages_by_file:

344

self.messages_by_file[msg.path] = []

345

346

self.messages_by_file[msg.path].append({

347

'line': msg.line,

348

'column': msg.column,

349

'severity': self.map_severity(msg.category),

350

'message': msg.msg,

351

'rule': msg.msg_id

352

})

353

354

def map_severity(self, category):

355

"""Map pylint categories to IDE severity levels."""

356

mapping = {

357

'E': 'error',

358

'F': 'error',

359

'W': 'warning',

360

'C': 'info',

361

'R': 'info',

362

'I': 'info'

363

}

364

return mapping.get(category, 'info')

365

366

def display_reports(self, layout):

367

"""Output IDE-friendly format."""

368

import json

369

result = {

370

'files': self.messages_by_file,

371

'summary': {

372

'total_files': len(self.messages_by_file),

373

'total_issues': sum(len(msgs) for msgs in self.messages_by_file.values())

374

}

375

}

376

json.dump(result, self.out, indent=2)

377

```

378

379

## Output Format Examples

380

381

### Text Reporter Output

382

383

```

384

************* Module mymodule

385

mymodule.py:10:0: C0111: Missing module docstring (missing-docstring)

386

mymodule.py:15:4: W0613: Unused argument 'param' (unused-argument)

387

mymodule.py:20:0: R0903: Too few public methods (1/2) (too-few-public-methods)

388

```

389

390

### JSON Reporter Output

391

392

```json

393

[

394

{

395

"type": "convention",

396

"module": "mymodule",

397

"obj": "",

398

"line": 10,

399

"column": 0,

400

"path": "mymodule.py",

401

"symbol": "missing-docstring",

402

"message": "Missing module docstring",

403

"message-id": "C0111"

404

},

405

{

406

"type": "warning",

407

"module": "mymodule",

408

"obj": "function_name",

409

"line": 15,

410

"column": 4,

411

"path": "mymodule.py",

412

"symbol": "unused-argument",

413

"message": "Unused argument 'param'",

414

"message-id": "W0613"

415

}

416

]

417

```

418

419

### Colorized Output

420

421

Terminal output with ANSI color codes for different message types:

422

- **Red**: Errors and fatal messages

423

- **Yellow**: Warnings

424

- **Blue**: Conventions and refactoring suggestions

425

- **Green**: Informational messages

426

427

## Reporter Configuration

428

429

### Command Line Reporter Selection

430

431

```bash

432

# Use specific reporter

433

pylint --output-format=json mymodule.py

434

pylint --output-format=colorized mymodule.py

435

436

# Output to file

437

pylint --output-format=json --output=results.json mymodule.py

438

439

# Use multiple reporters (with custom script)

440

pylint --load-plugins=custom_reporters --output-format=multi mymodule.py

441

```

442

443

### Programmatic Reporter Configuration

444

445

```python

446

from pylint.lint import PyLinter

447

from pylint.reporters import TextReporter

448

449

linter = PyLinter()

450

451

# Configure reporter options

452

reporter = TextReporter()

453

reporter.path_strip_prefix = '/project/root/'

454

455

linter.set_reporter(reporter)

456

457

# Configure report generation

458

linter.config.reports = True

459

linter.config.score = True

460

linter.config.msg_template = '{path}:{line}: {msg_id}: {msg}'

461

```