Skip to content

Commit 29e95c5

Browse files
author
Release Manager
committed
gh-36628: some simplifications in doctest/ folder (ruff C4) use `ruff check --fix --select=C4 src/sage/doctest` to fix a few details plus some manual tweaking afterwards ### 📝 Checklist - [x] The title is concise, informative, and self-explanatory. - [x] The description explains in detail what this PR is about. URL: #36628 Reported by: Frédéric Chapoton Reviewer(s): Matthias Köppe
2 parents 7354bdb + ecbd9ac commit 29e95c5

File tree

6 files changed

+59
-55
lines changed

6 files changed

+59
-55
lines changed

src/sage/doctest/control.py

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@
3636
import sys
3737
import time
3838
import json
39-
import re
4039
import shlex
4140
import types
4241
import sage.misc.flatten
@@ -66,6 +65,7 @@
6665
except ImportError:
6766
pass
6867

68+
6969
class DocTestDefaults(SageObject):
7070
"""
7171
This class is used for doctesting the Sage doctest module.
@@ -145,7 +145,7 @@ def __init__(self, **kwds):
145145
# automatically anyway. However, this default is still used for
146146
# displaying user-defined optional tags and we don't want to see
147147
# the auto_optional_tags there.
148-
self.optional = set(['sage']) | auto_optional_tags
148+
self.optional = {'sage'} | auto_optional_tags
149149
self.hide = ''
150150
self.probe = ''
151151

@@ -224,6 +224,7 @@ def skipdir(dirname):
224224
return True
225225
return False
226226

227+
227228
def skipfile(filename, tested_optional_tags=False, *,
228229
if_installed=False, log=None):
229230
"""
@@ -317,8 +318,8 @@ def skipfile(filename, tested_optional_tags=False, *,
317318
return file_tag_string
318319

319320
elif tested_optional_tags is not True:
320-
extra = set(tag for tag in file_optional_tags
321-
if tag not in tested_optional_tags)
321+
extra = {tag for tag in file_optional_tags
322+
if tag not in tested_optional_tags}
322323
if extra:
323324
file_tag_string = unparse_optional_tags(file_optional_tags, prefix='')
324325
if log:
@@ -445,7 +446,7 @@ def __init__(self, options, args):
445446
options.hidden_features = set()
446447
if isinstance(options.hide, str):
447448
if not len(options.hide):
448-
options.hide = set([])
449+
options.hide = set()
449450
else:
450451
s = options.hide.lower()
451452
options.hide = set(s.split(','))
@@ -455,12 +456,12 @@ def __init__(self, options, args):
455456
if 'all' in options.hide:
456457
options.hide.discard('all')
457458
from sage.features.all import all_features
458-
feature_names = set([f.name for f in all_features() if not f.is_standard()])
459+
feature_names = {f.name for f in all_features() if not f.is_standard()}
459460
options.hide = options.hide.union(feature_names)
460461
if 'optional' in options.hide:
461462
options.hide.discard('optional')
462463
from sage.features.all import all_features
463-
feature_names = set([f.name for f in all_features() if f.is_optional()])
464+
feature_names = {f.name for f in all_features() if f.is_optional()}
464465
options.hide = options.hide.union(feature_names)
465466

466467
options.disabled_optional = set()
@@ -1085,7 +1086,7 @@ def sort_sources(self):
10851086
"""
10861087
if self.options.nthreads > 1 and len(self.sources) > self.options.nthreads:
10871088
self.log("Sorting sources by runtime so that slower doctests are run first....")
1088-
default = dict(walltime=0)
1089+
default = {'walltime': 0}
10891090

10901091
def sort_key(source):
10911092
basename = source.basename
@@ -1153,7 +1154,7 @@ def run_doctests(self):
11531154
self.cleanup(False)
11541155
else:
11551156
self.log("No files to doctest")
1156-
self.reporter = DictAsObject(dict(error_status=0, stats={}))
1157+
self.reporter = DictAsObject({'error_status': 0, 'stats': {}})
11571158

11581159
def cleanup(self, final=True):
11591160
"""
@@ -1315,9 +1316,9 @@ def run_val_gdb(self, testing=False):
13151316
flags = os.getenv("SAGE_MEMCHECK_FLAGS")
13161317
if flags is None:
13171318
flags = "--leak-resolution=high --leak-check=full --num-callers=25 "
1318-
flags += '''--suppressions="%s" ''' % (os.path.join(SAGE_EXTCODE,"valgrind","pyalloc.supp"))
1319-
flags += '''--suppressions="%s" ''' % (os.path.join(SAGE_EXTCODE,"valgrind","sage.supp"))
1320-
flags += '''--suppressions="%s" ''' % (os.path.join(SAGE_EXTCODE,"valgrind","sage-additional.supp"))
1319+
flags += '''--suppressions="%s" ''' % (os.path.join(SAGE_EXTCODE,"valgrind", "pyalloc.supp"))
1320+
flags += '''--suppressions="%s" ''' % (os.path.join(SAGE_EXTCODE,"valgrind", "sage.supp"))
1321+
flags += '''--suppressions="%s" ''' % (os.path.join(SAGE_EXTCODE,"valgrind", "sage-additional.supp"))
13211322
elif opt.massif:
13221323
toolname = "massif"
13231324
flags = os.getenv("SAGE_MASSIF_FLAGS", "--depth=6 ")

src/sage/doctest/forker.py

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -687,10 +687,10 @@ def compiler(example):
687687
# findlinestarts() returns pairs (index, lineno) where
688688
# "index" is the index in the bytecode where the line
689689
# number changes to "lineno".
690-
linenumbers1 = set(lineno for (index, lineno)
691-
in findlinestarts(code))
692-
linenumbers2 = set(lineno for (index, lineno)
693-
in findlinestarts(execcode))
690+
linenumbers1 = {lineno for (index, lineno)
691+
in findlinestarts(code)}
692+
linenumbers2 = {lineno for (index, lineno)
693+
in findlinestarts(execcode)}
694694
if linenumbers1 != linenumbers2:
695695
raise SyntaxError("doctest is not a single statement")
696696

@@ -1726,7 +1726,7 @@ def serial_dispatch(self):
17261726

17271727
with tempfile.TemporaryFile() as outtmpfile:
17281728
result = DocTestTask(source)(self.controller.options,
1729-
outtmpfile, self.controller.logger)
1729+
outtmpfile, self.controller.logger)
17301730
outtmpfile.seek(0)
17311731
output = bytes_to_str(outtmpfile.read())
17321732

@@ -2334,7 +2334,7 @@ def save_result_output(self):
23342334
try:
23352335
self.result = self.result_queue.get(block=False)
23362336
except Empty:
2337-
self.result = (0, DictAsObject(dict(err='noresult')))
2337+
self.result = (0, DictAsObject({'err': 'noresult'}))
23382338
del self.result_queue
23392339

23402340
self.outtmpfile.seek(0)
@@ -2536,17 +2536,17 @@ def __call__(self, options, outtmpfile=None, msgfile=None, result_queue=None):
25362536
result = None
25372537
try:
25382538
runner = SageDocTestRunner(
2539-
SageOutputChecker(),
2540-
verbose=options.verbose,
2541-
outtmpfile=outtmpfile,
2542-
msgfile=msgfile,
2543-
sage_options=options,
2544-
optionflags=doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS)
2539+
SageOutputChecker(),
2540+
verbose=options.verbose,
2541+
outtmpfile=outtmpfile,
2542+
msgfile=msgfile,
2543+
sage_options=options,
2544+
optionflags=doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS)
25452545
runner.basename = self.source.basename
25462546
runner.filename = self.source.path
25472547
N = options.file_iterations
2548-
results = DictAsObject(dict(walltime=[], cputime=[],
2549-
err=None, walltime_skips=0))
2548+
results = DictAsObject({'walltime': [], 'cputime': [],
2549+
'err': None, 'walltime_skips': 0})
25502550

25512551
# multiprocessing.Process instances don't run exit
25522552
# functions, so we run the functions added by doctests
@@ -2571,7 +2571,7 @@ def __call__(self, options, outtmpfile=None, msgfile=None, result_queue=None):
25712571
except BaseException:
25722572
exc_info = sys.exc_info()
25732573
tb = "".join(traceback.format_exception(*exc_info))
2574-
result = (0, DictAsObject(dict(err=exc_info[0], tb=tb)))
2574+
result = (0, DictAsObject({'err': exc_info[0], 'tb': tb}))
25752575

25762576
if result_queue is not None:
25772577
result_queue.put(result, False)

src/sage/doctest/parsing.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ def fake_RIFtol(*args):
9494
ansi_escape_sequence = re.compile(r'(\x1b[@-Z\\-~]|\x1b\[.*?[@-~]|\x9b.*?[@-~])')
9595

9696
special_optional_regex = 'arb216|arb218|py2|long time|not implemented|not tested|known bug'
97-
tag_with_explanation_regex = fr'((?:\w|[.])+)\s*(?:\((.*?)\))?'
97+
tag_with_explanation_regex = r'((?:\w|[.])+)\s*(?:\((.*?)\))?'
9898
optional_regex = re.compile(fr'(?P<cmd>{special_optional_regex})\s*(?:\((?P<cmd_explanation>.*?)\))?|'
9999
fr'[^ a-z]\s*(optional|needs)(?:\s|[:-])*(?P<tags>(?:(?:{tag_with_explanation_regex})\s*)*)',
100100
re.IGNORECASE)
@@ -470,7 +470,7 @@ def update_optional_tags(line, tags=None, *, add_tags=None, remove_tags=None, fo
470470
| V V V V V V v v v v
471471
| sage: # optional - magma, needs sage.symbolic
472472
"""
473-
if not (m := re.match('( *sage: *)(.*)', line)):
473+
if not re.match('( *sage: *)(.*)', line):
474474
raise ValueError(f'line must start with a sage: prompt, got: {line}')
475475

476476
current_tags, line_sans_tags, is_persistent = parse_optional_tags(line.rstrip(), return_string_sans_tags=True)
@@ -1140,8 +1140,8 @@ def update_tag_counts(optional_tags):
11401140

11411141
def check_and_clear_tag_counts():
11421142
if (num_examples := tag_count_within_block['']) >= 4:
1143-
if overused_tags := set(tag for tag, count in tag_count_within_block.items()
1144-
if tag and count >= num_examples):
1143+
if overused_tags := {tag for tag, count in tag_count_within_block.items()
1144+
if tag and count >= num_examples}:
11451145
overused_tags.update(persistent_optional_tags)
11461146
overused_tags.difference_update(self.file_optional_tags)
11471147
suggested = unparse_optional_tags(overused_tags, prefix='sage: # ')
@@ -1210,10 +1210,10 @@ def check_and_clear_tag_counts():
12101210
continue
12111211

12121212
if self.optional_tags is not True:
1213-
extra = set(tag
1214-
for tag in optional_tags
1215-
if (tag not in self.optional_tags
1216-
and tag not in available_software))
1213+
extra = {tag
1214+
for tag in optional_tags
1215+
if (tag not in self.optional_tags
1216+
and tag not in available_software)}
12171217
if extra:
12181218
if any(tag in external_software for tag in extra):
12191219
# never probe "external" software

src/sage/doctest/reporting.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ def __init__(self, controller):
116116
sage: DTR = DocTestReporter(DC)
117117
"""
118118
self.controller = controller
119-
self.postscript = dict(lines=[], cputime=0, walltime=0)
119+
self.postscript = {"lines": [], "cputime": 0, "walltime": 0}
120120
self.sources_completed = 0
121121
self.stats = {}
122122
self.error_status = 0
@@ -408,7 +408,7 @@ def report(self, source, timeout, return_code, results, output, pid=None):
408408
ntests, result_dict = results
409409
except (TypeError, ValueError):
410410
ntests = 0
411-
result_dict = DictAsObject(dict(err='badresult'))
411+
result_dict = DictAsObject({"err": 'badresult'})
412412
if timeout:
413413
fail_msg = "Timed out"
414414
if ntests > 0:
@@ -429,7 +429,7 @@ def report(self, source, timeout, return_code, results, output, pid=None):
429429
log(output)
430430
log("*"*70)
431431
postscript['lines'].append(cmd + " # %s" % fail_msg)
432-
stats[basename] = dict(failed=True, walltime=1e6, ntests=ntests)
432+
stats[basename] = {"failed": True, "walltime": 1e6, "ntests": ntests}
433433
if not the_baseline_stats.get('failed', False):
434434
self.error_status |= 4
435435
elif return_code:
@@ -445,7 +445,7 @@ def report(self, source, timeout, return_code, results, output, pid=None):
445445
log(output)
446446
log("*"*70)
447447
postscript['lines'].append(cmd + " # %s" % fail_msg)
448-
stats[basename] = dict(failed=True, walltime=1e6, ntests=ntests)
448+
stats[basename] = {"failed": True, "walltime": 1e6, "ntests": ntests}
449449
if not the_baseline_stats.get('failed', False):
450450
self.error_status |= (8 if return_code > 0 else 16)
451451
else:
@@ -501,9 +501,9 @@ def report(self, source, timeout, return_code, results, output, pid=None):
501501
if hasattr(result_dict, 'tb'):
502502
log(result_dict.tb)
503503
if hasattr(result_dict, 'walltime'):
504-
stats[basename] = dict(failed=True, walltime=wall, ntests=ntests)
504+
stats[basename] = {"failed": True, "walltime": wall, "ntests": ntests}
505505
else:
506-
stats[basename] = dict(failed=True, walltime=1e6, ntests=ntests)
506+
stats[basename] = {"failed": True, "walltime": 1e6, "ntests": ntests}
507507
self.error_status |= 64
508508
if result_dict.err is None or result_dict.err == 'tab':
509509
f = result_dict.failures
@@ -515,16 +515,16 @@ def report(self, source, timeout, return_code, results, output, pid=None):
515515
if not the_baseline_stats.get('failed', False):
516516
self.error_status |= 1
517517
if f or result_dict.err == 'tab':
518-
stats[basename] = dict(failed=True, walltime=wall, ntests=ntests)
518+
stats[basename] = {"failed": True, "walltime": wall, "ntests": ntests}
519519
else:
520-
stats[basename] = dict(walltime=wall, ntests=ntests)
520+
stats[basename] = {"walltime": wall, "ntests": ntests}
521521
postscript['cputime'] += cpu
522522
postscript['walltime'] += wall
523523

524524
try:
525525
optionals = result_dict.optionals
526526
except AttributeError:
527-
optionals = dict()
527+
optionals = {}
528528
for tag in sorted(optionals):
529529
nskipped = optionals[tag]
530530
if tag == "long time":

src/sage/doctest/sources.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ def _process_doc(self, doctests, doc, namespace, start):
233233
new_doctests = self.parse_docstring(docstring, namespace, start)
234234
sig_on_count_doc_doctest = "sig_on_count() # check sig_on/off pairings (virtual doctest)\n"
235235
for dt in new_doctests:
236-
if len(dt.examples) > 0 and not (hasattr(dt.examples[-1],'sage_source')
236+
if len(dt.examples) > 0 and not (hasattr(dt.examples[-1], 'sage_source')
237237
and dt.examples[-1].sage_source == sig_on_count_doc_doctest):
238238
# Line number refers to the end of the docstring
239239
sigon = doctest.Example(sig_on_count_doc_doctest, "0\n", lineno=docstring.count("\n"))
@@ -305,7 +305,7 @@ def _create_doctests(self, namespace, tab_okay=None):
305305
False
306306
"""
307307
if tab_okay is None:
308-
tab_okay = isinstance(self,TexSource)
308+
tab_okay = isinstance(self, TexSource)
309309
self._init()
310310
self.line_shift = 0
311311
self.parser = SageDocTestParser(self.options.optional,
@@ -371,9 +371,9 @@ def _create_doctests(self, namespace, tab_okay=None):
371371
if unparsed_doc:
372372
self._process_doc(doctests, doc, namespace, start)
373373

374-
extras = dict(tab=not tab_okay and tab_locations,
375-
line_number=contains_line_number,
376-
optionals=self.parser.optionals)
374+
extras = {"tab": not tab_okay and tab_locations,
375+
"line_number": contains_line_number,
376+
"optionals": self.parser.optionals}
377377
if self.options.randorder is not None and self.options.randorder is not False:
378378
# we want to randomize even when self.randorder = 0
379379
random.seed(self.options.randorder)
@@ -569,13 +569,13 @@ def __init__(self, path, options):
569569
base, ext = os.path.splitext(path)
570570
valid_code_ext = ('.py', '.pyx', '.pxd', '.pxi', '.sage', '.spyx')
571571
if ext in valid_code_ext:
572-
self.__class__ = dynamic_class('PythonFileSource',(FileDocTestSource,PythonSource))
572+
self.__class__ = dynamic_class('PythonFileSource', (FileDocTestSource, PythonSource))
573573
self.encoding = "utf-8"
574574
elif ext == '.tex':
575-
self.__class__ = dynamic_class('TexFileSource',(FileDocTestSource,TexSource))
575+
self.__class__ = dynamic_class('TexFileSource', (FileDocTestSource, TexSource))
576576
self.encoding = "utf-8"
577577
elif ext == '.rst' or ext == '.rst.txt':
578-
self.__class__ = dynamic_class('RestFileSource',(FileDocTestSource,RestSource))
578+
self.__class__ = dynamic_class('RestFileSource', (FileDocTestSource, RestSource))
579579
self.encoding = "utf-8"
580580
else:
581581
valid_ext = ", ".join(valid_code_ext + ('.tex', '.rst', '.rst.txt'))
@@ -955,6 +955,7 @@ def parse_docstring(self, docstring, namespace, start):
955955
return [self.parser.get_doctest(docstring, namespace, str(self.qualified_name),
956956
self.printpath, start + 1)]
957957

958+
958959
class PythonSource(SourceLanguage):
959960
"""
960961
This class defines the functions needed for the extraction of doctests from python sources.
@@ -1252,6 +1253,7 @@ def _neutralize_doctests(self, reindent):
12521253
neutralized.append(" "*reindent + line)
12531254
return "".join(neutralized)
12541255

1256+
12551257
class TexSource(SourceLanguage):
12561258
"""
12571259
This class defines the functions needed for the extraction of
@@ -1628,6 +1630,7 @@ def parse_docstring(self, docstring, namespace, start):
16281630
self.printpath, start + 1)
16291631
return [outer_doctest] + inner_doctests
16301632

1633+
16311634
class DictAsObject(dict):
16321635
"""
16331636
A simple subclass of dict that inserts the items from the initializing dictionary into attributes.

src/sage/doctest/util.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ def dict_difference(self, other):
8181
sage: dict_difference(D2.__dict__, D1.__dict__)
8282
{'foobar': 'hello', 'timeout': 100}
8383
"""
84-
D = dict()
84+
D = {}
8585
for k, v in self.items():
8686
try:
8787
if other[k] == v:
@@ -275,8 +275,8 @@ def start(self):
275275
sage: D.start(); D.set
276276
set()
277277
"""
278-
self.set = set([])
279-
self.got = set([])
278+
self.set = set()
279+
self.got = set()
280280

281281
def __getitem__(self, name):
282282
"""

0 commit comments

Comments
 (0)