or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

analysis-runner.mdconfiguration.mdexceptions.mdfile-finding.mdformatters.mdindex.mdmessages.mdprofiles.mdtools.md

profiles.mddocs/

0

# Profiles

1

2

Configuration profile system for managing tool settings, rules, and project-specific configurations. Profiles allow customization of Prospector's behavior for different projects and coding styles.

3

4

## Capabilities

5

6

### ProspectorProfile Class

7

8

Main configuration profile class that manages tool settings and rules.

9

10

```python { .api }

11

class ProspectorProfile:

12

pass

13

```

14

15

Represents a configuration profile with tool settings, enabled/disabled rules, and other preferences.

16

17

```python { .api }

18

@staticmethod

19

def load(name: Union[str, Path], profile_path: list[Path],

20

forced_inherits: Optional[list[str]] = None) -> ProspectorProfile

21

```

22

23

Loads a profile from the filesystem or built-in profiles.

24

25

**Parameters:**

26

- `name`: Union[str, Path] - Profile name or path to profile file

27

- `profile_path`: list[Path] - List of directories to search for profiles

28

- `forced_inherits`: Optional[list[str]] - Additional profiles to inherit from

29

30

**Returns:**

31

- `ProspectorProfile` - Loaded and configured profile

32

33

**Raises:**

34

- `ProfileNotFound` - If the specified profile cannot be found

35

- `CannotParseProfile` - If the profile file contains invalid YAML

36

37

**Profile Search Order:**

38

1. Explicit path if `name` is a Path

39

2. Directories in `profile_path` list

40

3. Built-in profiles directory

41

4. Python packages named `prospector_profile_{module_name}`

42

43

```python { .api }

44

def is_tool_enabled(self, tool_name: str) -> Optional[bool]

45

```

46

47

Checks if a specific tool is enabled in this profile.

48

49

**Parameters:**

50

- `tool_name`: str - Name of the tool to check

51

52

**Returns:**

53

- `Optional[bool]` - True if enabled, False if disabled, None if not specified

54

55

```python { .api }

56

def get_disabled_messages(self, tool_name: str) -> list[str]

57

```

58

59

Gets list of message codes disabled for a specific tool.

60

61

**Parameters:**

62

- `tool_name`: str - Name of the tool

63

64

**Returns:**

65

- `list[str]` - List of disabled message codes

66

67

```python { .api }

68

def get_enabled_messages(self, tool_name: str) -> list[str]

69

```

70

71

Gets list of message codes enabled for a specific tool.

72

73

**Parameters:**

74

- `tool_name`: str - Name of the tool

75

76

**Returns:**

77

- `list[str]` - List of enabled message codes

78

79

```python { .api }

80

def list_profiles(self) -> list[str]

81

```

82

83

Lists all profiles that were loaded (including inherited profiles).

84

85

**Returns:**

86

- `list[str]` - List of profile names in inheritance order

87

88

### Profile Properties

89

90

Profile objects have various properties for accessing configuration:

91

92

- `autodetect`: bool - Whether to auto-detect libraries and frameworks

93

- `uses`: list[str] - Explicitly specified libraries/frameworks to use

94

- `ignore_patterns`: list[str] - Regex patterns for files to ignore

95

- `ignore_paths`: list[str] - Specific paths to ignore

96

- `output_format`: str - Default output format

97

- `output_target`: list[str] - Default output target files

98

99

### Auto-Loaded Profiles

100

101

```python { .api }

102

AUTO_LOADED_PROFILES: list[Path]

103

```

104

105

List of profile filenames that Prospector automatically searches for in the working directory.

106

107

**Auto-loaded Profile Files:**

108

- `.landscape.yml` / `.landscape.yaml`

109

- `landscape.yml` / `landscape.yaml`

110

- `.prospector.yml` / `.prospector.yaml`

111

- `prospector.yml` / `prospector.yaml`

112

- `prospector/.prospector.yml` / `prospector/.prospector.yaml`

113

- `prospector/prospector.yml` / `prospector/prospector.yaml`

114

- `.prospector/.prospector.yml` / `.prospector/.prospector.yaml`

115

- `.prospector/prospector.yml` / `.prospector/prospector.yaml`

116

117

### Profile Exceptions

118

119

```python { .api }

120

class ProfileNotFound(Exception):

121

def __init__(self, name: str, profile_path: list[Path]) -> None

122

```

123

124

Raised when a requested profile cannot be found.

125

126

**Properties:**

127

- `name`: str - Name of the profile that wasn't found

128

- `profile_path`: list[Path] - Search paths that were checked

129

130

```python { .api }

131

class CannotParseProfile(Exception):

132

def __init__(self, filepath: Path, parse_error: Any) -> None

133

```

134

135

Raised when a profile file contains invalid YAML or configuration.

136

137

**Properties:**

138

- `filepath`: Path - Path to the problematic profile file

139

- `parse_error`: Any - The underlying parsing error

140

141

```python { .api }

142

def get_parse_message(self) -> str

143

```

144

145

Gets a human-readable error message describing the parse failure.

146

147

## Usage Examples

148

149

### Loading Profiles

150

151

```python

152

from prospector.profiles.profile import ProspectorProfile

153

from pathlib import Path

154

155

# Load default profile

156

try:

157

profile = ProspectorProfile.load("default", [Path("/usr/share/prospector/profiles")])

158

print(f"Loaded profile with {len(profile.list_profiles())} inherited profiles")

159

except Exception as e:

160

print(f"Failed to load profile: {e}")

161

162

# Load custom profile from specific location

163

profile_paths = [

164

Path(".prospector"),

165

Path("/etc/prospector/profiles"),

166

Path.home() / ".config/prospector/profiles"

167

]

168

169

try:

170

profile = ProspectorProfile.load("myproject", profile_paths)

171

print("Loaded custom profile")

172

except Exception as e:

173

print(f"Custom profile not found: {e}")

174

```

175

176

### Checking Tool Configuration

177

178

```python

179

from prospector.profiles.profile import ProspectorProfile

180

from pathlib import Path

181

182

profile = ProspectorProfile.load("default", [Path("/usr/share/prospector/profiles")])

183

184

# Check which tools are enabled

185

tools_to_check = ["pylint", "pyflakes", "mypy", "bandit"]

186

187

for tool in tools_to_check:

188

enabled = profile.is_tool_enabled(tool)

189

if enabled is True:

190

print(f"{tool}: enabled")

191

elif enabled is False:

192

print(f"{tool}: disabled")

193

else:

194

print(f"{tool}: not specified (use default)")

195

196

# Check disabled messages for pylint

197

disabled = profile.get_disabled_messages("pylint")

198

if disabled:

199

print(f"Pylint disabled messages: {disabled}")

200

201

# Check enabled messages for pydocstyle

202

enabled = profile.get_enabled_messages("pydocstyle")

203

if enabled:

204

print(f"Pydocstyle enabled messages: {enabled}")

205

```

206

207

### Creating Profile Files

208

209

```yaml

210

# Example .prospector.yaml file

211

strictness: medium

212

test-warnings: false

213

doc-warnings: true

214

autodetect: true

215

216

uses:

217

- django

218

- celery

219

220

ignore-patterns:

221

- '(^|/)migrations(/|$)'

222

- '\.pb2\.py$'

223

224

ignore-paths:

225

- docs

226

- build

227

- venv

228

229

output-format: grouped

230

231

pylint:

232

disable:

233

- missing-docstring

234

- invalid-name

235

options:

236

max-line-length: 120

237

238

pycodestyle:

239

disable:

240

- E501 # line too long

241

options:

242

max-line-length: 120

243

244

mypy:

245

run: true

246

options:

247

ignore-missing-imports: true

248

```

249

250

### Working with Profile Inheritance

251

252

```python

253

from prospector.profiles.profile import ProspectorProfile

254

from pathlib import Path

255

256

# Load profile with forced inheritance

257

profile = ProspectorProfile.load(

258

"myproject",

259

[Path(".prospector")],

260

forced_inherits=["strictness_high", "django"]

261

)

262

263

# See what profiles were loaded

264

profiles = profile.list_profiles()

265

print(f"Profile inheritance chain: {' -> '.join(profiles)}")

266

267

# Check if specific settings come from inheritance

268

if profile.autodetect:

269

print("Auto-detection is enabled")

270

271

libraries = profile.uses

272

if libraries:

273

print(f"Configured for libraries: {libraries}")

274

```

275

276

### Error Handling

277

278

```python

279

from prospector.profiles.profile import ProspectorProfile, ProfileNotFound, CannotParseProfile

280

from pathlib import Path

281

282

def load_profile_safely(name: str, search_paths: list[Path]) -> ProspectorProfile:

283

try:

284

return ProspectorProfile.load(name, search_paths)

285

except ProfileNotFound as e:

286

print(f"Profile '{e.name}' not found in paths: {e.profile_path}")

287

print("Falling back to default profile")

288

return ProspectorProfile.load("default", search_paths)

289

except CannotParseProfile as e:

290

print(f"Failed to parse profile file {e.filepath}:")

291

print(e.get_parse_message())

292

raise

293

294

# Usage

295

search_paths = [Path("."), Path("/etc/prospector")]

296

profile = load_profile_safely("myproject", search_paths)

297

```

298

299

### Auto-Detection of Profiles

300

301

```python

302

from prospector.profiles import AUTO_LOADED_PROFILES

303

from pathlib import Path

304

import os

305

306

def find_auto_profile(working_dir: Path) -> Optional[Path]:

307

"""Find automatically loaded profile in working directory"""

308

for profile_path in AUTO_LOADED_PROFILES:

309

full_path = working_dir / profile_path

310

if full_path.exists() and full_path.is_file():

311

return full_path

312

return None

313

314

# Check current directory

315

current_dir = Path.cwd()

316

auto_profile = find_auto_profile(current_dir)

317

318

if auto_profile:

319

print(f"Found auto-loaded profile: {auto_profile}")

320

# This profile would be automatically loaded by ProspectorConfig

321

else:

322

print("No auto-loaded profile found")

323

print("Checked for these files:")

324

for profile_path in AUTO_LOADED_PROFILES:

325

print(f" {profile_path}")

326

```

327

328

### Dynamic Profile Configuration

329

330

```python

331

from prospector.profiles.profile import ProspectorProfile

332

from prospector.config import ProspectorConfig

333

from pathlib import Path

334

335

def configure_for_project(project_type: str) -> ProspectorConfig:

336

"""Configure Prospector based on project type"""

337

338

# Determine appropriate profiles

339

if project_type == "django":

340

forced_inherits = ["django", "strictness_medium"]

341

elif project_type == "flask":

342

forced_inherits = ["flask", "strictness_medium"]

343

elif project_type == "library":

344

forced_inherits = ["strictness_high", "doc_warnings"]

345

else:

346

forced_inherits = ["strictness_medium"]

347

348

# Create config with custom profile loading

349

config = ProspectorConfig()

350

351

# Override profile with project-specific settings

352

profile_paths = [

353

Path(".prospector"),

354

Path("/etc/prospector/profiles")

355

]

356

357

try:

358

profile = ProspectorProfile.load(

359

"default",

360

profile_paths,

361

forced_inherits=forced_inherits

362

)

363

config.profile = profile

364

print(f"Configured for {project_type} project")

365

except Exception as e:

366

print(f"Failed to configure for {project_type}: {e}")

367

368

return config

369

370

# Usage

371

django_config = configure_for_project("django")

372

library_config = configure_for_project("library")

373

```

374

375

### Profile Validation

376

377

```python

378

from prospector.profiles.profile import ProspectorProfile

379

from pathlib import Path

380

import yaml

381

382

def validate_profile_file(profile_path: Path) -> bool:

383

"""Validate a profile file before loading"""

384

try:

385

# Check if file exists and is readable

386

if not profile_path.exists():

387

print(f"Profile file does not exist: {profile_path}")

388

return False

389

390

# Try to parse as YAML

391

with open(profile_path, 'r') as f:

392

yaml.safe_load(f)

393

394

# Try to load as Prospector profile

395

ProspectorProfile.load(str(profile_path), [profile_path.parent])

396

397

print(f"Profile file is valid: {profile_path}")

398

return True

399

400

except yaml.YAMLError as e:

401

print(f"YAML syntax error in {profile_path}: {e}")

402

return False

403

except Exception as e:

404

print(f"Profile validation failed for {profile_path}: {e}")

405

return False

406

407

# Validate profile files

408

profile_files = [

409

Path(".prospector.yaml"),

410

Path("profiles/myproject.yaml"),

411

Path("profiles/strict.yaml")

412

]

413

414

for profile_file in profile_files:

415

validate_profile_file(profile_file)

416

```