or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-analysis.mddata-extraction.mdindex.mdrating-system.md

rating-system.mddocs/

0

# Rating System

1

2

Comprehensive quality assessment system with pluggable tests that evaluate various aspects of Python packaging best practices. The rating system provides detailed feedback, actionable recommendations, and numerical scores from 0-10 with humorous cheese-themed descriptions.

3

4

## Capabilities

5

6

### Core Rating Function

7

8

**rate(data, skip_tests=None)**

9

10

```python { .api }

11

def rate(data, skip_tests=None):

12

"""Rate package metadata quality using comprehensive test suite.

13

14

Args:

15

data: Package metadata dictionary from data extraction modules

16

skip_tests: List of test class names to skip during evaluation

17

18

Returns:

19

tuple: (rating: int, failures: list[str])

20

- rating: Numerical score from 0-10

21

- failures: List of failure messages for failed tests

22

23

Example:

24

>>> data = projectdata.get_data('/path/to/project')

25

>>> rating, failures = rate(data)

26

>>> print(f"Rating: {rating}/10")

27

>>> for failure in failures:

28

... print(f"- {failure}")

29

"""

30

```

31

32

The main rating function that:

33

34

- Runs all enabled tests against package metadata

35

- Calculates weighted score based on test importance

36

- Returns detailed failure messages for improvement guidance

37

- Supports fatal tests that force rating to 0

38

- Handles test skipping for specific use cases

39

40

### Test Discovery

41

42

**get_all_tests()**

43

44

```python { .api }

45

def get_all_tests():

46

"""Get list of all available test class names.

47

48

Returns:

49

list: List of test class names for use with skip_tests parameter

50

51

Example:

52

['Name', 'Version', 'VersionIsString', 'PEPVersion', 'Description',

53

'LongDescription', 'Classifiers', 'ClassifierVerification', ...]

54

"""

55

```

56

57

**get_code_licenses()**

58

59

```python { .api }

60

def get_code_licenses():

61

"""Build mapping of license short codes to classifier strings.

62

63

Returns:

64

dict: Mapping from license codes (e.g., 'MIT', 'GPL') to

65

sets of corresponding trove classifiers

66

67

Example:

68

{'MIT': {'License :: OSI Approved :: MIT License'},

69

'GPL': {'License :: OSI Approved :: GNU General Public License v2 (GPLv2)', ...}}

70

"""

71

```

72

73

### Constants and Configuration

74

75

**ALL_TESTS**

76

77

```python { .api }

78

ALL_TESTS: list

79

"""List of all available test instances.

80

81

Contains instantiated test objects for all quality checks.

82

Used internally by the rating system to run evaluations.

83

"""

84

```

85

86

**LEVELS**

87

88

```python { .api }

89

LEVELS: list

90

"""Rating descriptions with cheese-themed messages.

91

92

Index corresponds to rating (0-10):

93

- 0: "This cheese seems to contain no dairy products"

94

- 1: "Vieux Bologne"

95

- 2: "Limburger"

96

- ...

97

- 10: "Your cheese is so fresh most people think it's a cream: Mascarpone"

98

"""

99

```

100

101

**CODE_LICENSES**

102

103

```python { .api }

104

CODE_LICENSES: dict

105

"""Mapping of license codes to trove classifier sets.

106

107

Built from trove-classifiers package, provides lookup from

108

common license abbreviations to their full classifier names.

109

"""

110

```

111

112

**PEP386_RE**

113

114

```python { .api }

115

PEP386_RE: re.Pattern

116

"""Compiled regex pattern for validating PEP-386 version format.

117

118

Used internally by PEPVersion test to validate legacy version formats.

119

Matches versions like '1.0', '1.0.1', '1.0a1', '1.0.post1', '1.0.dev1'.

120

"""

121

```

122

123

**PEP440_RE**

124

125

```python { .api }

126

PEP440_RE: re.Pattern

127

"""Compiled regex pattern for validating PEP-440 version format.

128

129

Used internally by PEPVersion test to validate modern version formats.

130

Supports epochs, pre-releases, post-releases, dev releases, and local versions.

131

"""

132

```

133

134

**SHORT_NAME_RE**

135

136

```python { .api }

137

SHORT_NAME_RE: re.Pattern

138

"""Compiled regex pattern for extracting license short names from classifiers.

139

140

Used by get_code_licenses() to parse license abbreviations from

141

trove classifier strings like 'License :: OSI Approved :: MIT License'.

142

"""

143

```

144

145

## Test Classes

146

147

The rating system includes comprehensive tests organized by category:

148

149

### Fatal Tests

150

151

Tests that must pass for any meaningful rating:

152

153

**Name**

154

- Verifies package has a name field

155

- Fatal: Package receives rating 0 if missing

156

157

**Version**

158

- Verifies package has a version field

159

- Fatal: Package receives rating 0 if missing

160

161

### Version Validation

162

163

**VersionIsString**

164

- Ensures version is a string type (weight: 50)

165

166

**PEPVersion**

167

- Validates version format against PEP-440 standard (weight: 50)

168

- Gives reduced weight for PEP-386 compliance only (weight: 10)

169

170

### Description and Documentation

171

172

**Description**

173

- Checks for package description > 10 characters (weight: 100)

174

- Fatal if no description exists

175

176

**LongDescription**

177

- Verifies long description > 100 characters (weight: 50)

178

179

**ValidREST**

180

- Validates ReStructuredText syntax in long description (weight: 50)

181

- Skips validation for markdown/plain text content types

182

183

### Metadata Completeness

184

185

**Classifiers**

186

- Requires presence of trove classifiers (weight: 100)

187

188

**ClassifierVerification**

189

- Validates classifiers against official trove classifier list (weight: 20)

190

- Allows private classifiers with "Private :: " prefix

191

192

**PythonClassifierVersion**

193

- Checks for specific Python version classifiers (weight: 25-100)

194

- Higher weight for detailed version specifications

195

196

**PythonRequiresVersion**

197

- Validates python_requires field with PEP-508 syntax (weight: 100)

198

199

**Keywords**

200

- Checks for keywords field (weight: 20)

201

202

### Contact Information

203

204

**Author**

205

- Requires author field or author name in author_email (weight: 100)

206

207

**AuthorEmail**

208

- Requires author_email field (weight: 100)

209

210

**Url**

211

- Requires project URL or project_urls field (weight: 20)

212

213

### Licensing

214

215

**Licensing**

216

- Validates license information consistency (weight: 50)

217

- Checks license field, license_expression, and license classifiers

218

- Prevents ambiguous license specifications

219

220

**DevStatusClassifier**

221

- Encourages development status classifier (weight: 20)

222

223

### Distribution and Maintenance

224

225

**SDist**

226

- Checks for source distribution on PyPI (weight: 100)

227

- Only applies to PyPI analysis mode

228

229

**BusFactor**

230

- Evaluates number of package owners on PyPI (weight: 50-100)

231

- Encourages multiple maintainers for reliability

232

233

### Build System Validation

234

235

**MissingBuildSystem**

236

- Warns about setup.cfg without build system definition (weight: 200)

237

238

**MissingPyProjectToml**

239

- Encourages pyproject.toml adoption (weight: 100)

240

241

**StoneAgeSetupPy**

242

- Warns about outdated setup.py usage (weight: 200)

243

244

### Optional Tests

245

246

**CheckManifest**

247

- Integrates check-manifest tool if available (weight: dynamic)

248

- Validates MANIFEST.in completeness and packaging consistency

249

- Weight starts at 0, becomes 200 when applicable to project

250

- Only runs if check-manifest package is installed and project has a path

251

- Detects missing files in source distributions

252

- Helps ensure all necessary files are included in published packages

253

254

## Usage Examples

255

256

```python

257

from pyroma.ratings import rate, get_all_tests, LEVELS

258

from pyroma.projectdata import get_data

259

260

# Basic rating

261

data = get_data('/path/to/project')

262

rating, failures = rate(data)

263

print(f"Rating: {rating}/10 - {LEVELS[rating]}")

264

265

# Skip specific tests

266

rating, failures = rate(data, skip_tests=['BusFactor', 'SDist'])

267

268

# List available tests

269

tests = get_all_tests()

270

print("Available tests:", ', '.join(tests))

271

272

# Detailed analysis

273

if failures:

274

print("Issues found:")

275

for failure in failures:

276

print(f" - {failure}")

277

else:

278

print("No issues found!")

279

```

280

281

## Test Base Classes

282

283

**BaseTest**

284

285

```python { .api }

286

class BaseTest:

287

"""Base class for all quality assessment tests.

288

289

Attributes:

290

fatal: bool - If True, failure results in rating 0

291

weight: int - Relative importance for scoring (default varies)

292

"""

293

294

fatal: bool = False

295

weight: int

296

297

def test(self, data): ...

298

def message(self): ...

299

```

300

301

**FieldTest**

302

303

```python { .api }

304

class FieldTest(BaseTest):

305

"""Base class for tests checking field presence and non-emptiness.

306

307

Attributes:

308

field: str - Metadata field name to check

309

"""

310

311

field: str

312

313

def test(self, data): ...

314

def message(self): ...

315

```