Skip to content

Commit 574fbf3

Browse files
rtobarJulienPalard
authored andcommitted
Handle optional sorting of errors before reporting
Users can specify now a command-line option to sort errors before they are reported to stdout. When no option is given, errors are reported as they are generated, preserving backwards compatibility. When given, a comma-delimited list of field names must be given, with errors being sorted by the first field, then the second, and so on. Signed-off-by: Rodrigo Tobar <[email protected]>
1 parent 03d1dfa commit 574fbf3

File tree

1 file changed

+61
-8
lines changed

1 file changed

+61
-8
lines changed

sphinxlint/__main__.py

Lines changed: 61 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import argparse
2+
import enum
23
import multiprocessing
34
import os
45
import sys
@@ -9,6 +10,18 @@
910
from sphinxlint.sphinxlint import CheckersOptions
1011

1112

13+
class SortField(enum.Enum):
14+
"""Fields available for sorting error reports"""
15+
16+
FILENAME = 0
17+
LINE = 1
18+
ERROR_TYPE = 2
19+
20+
@staticmethod
21+
def as_supported_options():
22+
return ",".join(field.name.lower() for field in SortField)
23+
24+
1225
def parse_args(argv=None):
1326
"""Parse command line argument."""
1427
if argv is None:
@@ -33,6 +46,18 @@ def __call__(self, parser, namespace, values, option_string=None):
3346
else:
3447
enabled_checkers_names.difference_update(values.split(","))
3548

49+
class StoreSortFieldAction(argparse.Action):
50+
def __call__(self, parser, namespace, values, option_string=None):
51+
sort_fields = []
52+
for field_name in values.split(","):
53+
try:
54+
sort_fields.append(SortField[field_name.upper()])
55+
except KeyError:
56+
raise ValueError(
57+
f"Unsupported sort field: {field_name}, supported values are {SortField.as_supported_options()}"
58+
) from None
59+
setattr(namespace, self.dest, sort_fields)
60+
3661
parser.add_argument(
3762
"-v",
3863
"--verbose",
@@ -77,6 +102,14 @@ def __call__(self, parser, namespace, values, option_string=None):
77102
default=80,
78103
type=int,
79104
)
105+
parser.add_argument(
106+
"-s",
107+
"--sort-by",
108+
action=StoreSortFieldAction,
109+
help="comma-separated list of fields used to sort errors by. Available "
110+
f"fields are: {SortField.as_supported_options()}",
111+
)
112+
80113
parser.add_argument("paths", default=".", nargs="*")
81114
args = parser.parse_args(argv[1:])
82115
try:
@@ -116,13 +149,31 @@ def _check_file(todo):
116149
return check_file(*todo)
117150

118151

119-
def print_results(results):
120-
"""Print results (or a message if nothing is to be printed)."""
152+
def sort_errors(results, sorted_by):
153+
"""Flattens and potentially sorts errors based on user prefernces"""
154+
if not sorted_by:
155+
for results in results:
156+
yield from results
157+
return
158+
errors = list(error for errors in results for error in errors)
159+
# sorting is stable in python, so we can sort in reverse order to get the
160+
# ordering specified by the user
161+
for sort_field in reversed(sorted_by):
162+
if sort_field == SortField.ERROR_TYPE:
163+
errors.sort(key=lambda error: error.checker_name)
164+
elif sort_field == SortField.FILENAME:
165+
errors.sort(key=lambda error: error.filename)
166+
elif sort_field == SortField.LINE:
167+
errors.sort(key=lambda error: error.line_no)
168+
yield from errors
169+
170+
171+
def print_errors(errors):
172+
"""Print errors (or a message if nothing is to be printed)."""
121173
qty = 0
122-
for result in results:
123-
for error in result:
124-
print(error)
125-
qty += 1
174+
for error in errors:
175+
print(error)
176+
qty += 1
126177
if qty == 0:
127178
print("No problems found.")
128179
return qty
@@ -156,10 +207,12 @@ def main(argv=None):
156207
]
157208

158209
if len(todo) < 8:
159-
count = print_results(starmap(check_file, todo))
210+
count = print_errors(sort_errors(starmap(check_file, todo), args.sort_by))
160211
else:
161212
with multiprocessing.Pool() as pool:
162-
count = print_results(pool.imap_unordered(_check_file, todo))
213+
count = print_errors(
214+
sort_errors(pool.imap_unordered(_check_file, todo), args.sort_by)
215+
)
163216
pool.close()
164217
pool.join()
165218

0 commit comments

Comments
 (0)