Skip to content

Commit 31aa19a

Browse files
Avoid mutable default arguments (#342)
While they are not always an actual bug, they are certainly a Python anti-pattern and possible the source of future bugs. In at least one case, the default mutable argument `config` is actually modified later on by the function.
1 parent 1668dd9 commit 31aa19a

File tree

4 files changed

+30
-12
lines changed

4 files changed

+30
-12
lines changed

numpydoc/docscrape.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ class NumpyDocString(Mapping):
136136
'index': {}
137137
}
138138

139-
def __init__(self, docstring, config={}):
139+
def __init__(self, docstring, config=None):
140140
orig_docstring = docstring
141141
docstring = textwrap.dedent(docstring).split('\n')
142142

@@ -553,14 +553,16 @@ def dedent_lines(lines):
553553

554554

555555
class FunctionDoc(NumpyDocString):
556-
def __init__(self, func, role='func', doc=None, config={}):
556+
def __init__(self, func, role='func', doc=None, config=None):
557557
self._f = func
558558
self._role = role # e.g. "func" or "meth"
559559

560560
if doc is None:
561561
if func is None:
562562
raise ValueError("No function or docstring given")
563563
doc = inspect.getdoc(func) or ''
564+
if config is None:
565+
config = {}
564566
NumpyDocString.__init__(self, doc, config)
565567

566568
def get_func(self):
@@ -590,8 +592,10 @@ def __str__(self):
590592

591593

592594
class ObjDoc(NumpyDocString):
593-
def __init__(self, obj, doc=None, config={}):
595+
def __init__(self, obj, doc=None, config=None):
594596
self._f = obj
597+
if config is None:
598+
config = {}
595599
NumpyDocString.__init__(self, doc, config=config)
596600

597601

@@ -600,7 +604,7 @@ class ClassDoc(NumpyDocString):
600604
extra_public_methods = ['__call__']
601605

602606
def __init__(self, cls, doc=None, modulename='', func_doc=FunctionDoc,
603-
config={}):
607+
config=None):
604608
if not inspect.isclass(cls) and cls is not None:
605609
raise ValueError("Expected a class or None, but got %r" % cls)
606610
self._cls = cls
@@ -610,6 +614,8 @@ def __init__(self, cls, doc=None, modulename='', func_doc=FunctionDoc,
610614
else:
611615
ALL = object()
612616

617+
if config is None:
618+
config = {}
613619
self.show_inherited_members = config.get(
614620
'show_inherited_class_members', True)
615621

@@ -679,7 +685,7 @@ def _is_show_member(self, name):
679685
return True
680686

681687

682-
def get_doc_object(obj, what=None, doc=None, config={}):
688+
def get_doc_object(obj, what=None, doc=None, config=None):
683689
if what is None:
684690
if inspect.isclass(obj):
685691
what = 'class'
@@ -689,6 +695,8 @@ def get_doc_object(obj, what=None, doc=None, config={}):
689695
what = 'function'
690696
else:
691697
what = 'object'
698+
if config is None:
699+
config = {}
692700

693701
if what == 'class':
694702
return ClassDoc(obj, func_doc=FunctionDoc, doc=doc, config=config)

numpydoc/docscrape_sphinx.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@
1818

1919

2020
class SphinxDocString(NumpyDocString):
21-
def __init__(self, docstring, config={}):
21+
def __init__(self, docstring, config=None):
22+
if config is None:
23+
config = {}
2224
NumpyDocString.__init__(self, docstring, config=config)
2325
self.load_config(config)
2426

@@ -392,25 +394,31 @@ def __str__(self, indent=0, func_role="obj"):
392394

393395

394396
class SphinxFunctionDoc(SphinxDocString, FunctionDoc):
395-
def __init__(self, obj, doc=None, config={}):
397+
def __init__(self, obj, doc=None, config=None):
398+
if config is None:
399+
config = {}
396400
self.load_config(config)
397401
FunctionDoc.__init__(self, obj, doc=doc, config=config)
398402

399403

400404
class SphinxClassDoc(SphinxDocString, ClassDoc):
401-
def __init__(self, obj, doc=None, func_doc=None, config={}):
405+
def __init__(self, obj, doc=None, func_doc=None, config=None):
406+
if config is None:
407+
config = {}
402408
self.load_config(config)
403409
ClassDoc.__init__(self, obj, doc=doc, func_doc=None, config=config)
404410

405411

406412
class SphinxObjDoc(SphinxDocString, ObjDoc):
407-
def __init__(self, obj, doc=None, config={}):
413+
def __init__(self, obj, doc=None, config=None):
414+
if config is None:
415+
config = {}
408416
self.load_config(config)
409417
ObjDoc.__init__(self, obj, doc=doc, config=config)
410418

411419

412420
# TODO: refactor to use docscrape.get_doc_object
413-
def get_doc_object(obj, what=None, doc=None, config={}, builder=None):
421+
def get_doc_object(obj, what=None, doc=None, config=None, builder=None):
414422
if what is None:
415423
if inspect.isclass(obj):
416424
what = 'class'
@@ -421,6 +429,8 @@ def get_doc_object(obj, what=None, doc=None, config={}, builder=None):
421429
else:
422430
what = 'object'
423431

432+
if config is None:
433+
config = {}
424434
template_dirs = [os.path.join(os.path.dirname(__file__), 'templates')]
425435
if builder is not None:
426436
template_loader = BuiltinTemplateLoader()

numpydoc/tests/test_docscrape.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ def test_returns(doc):
225225
assert arg_type == 'ndarray'
226226
assert desc[0].startswith('The drawn samples')
227227
assert desc[-1].endswith('distribution.')
228-
228+
229229
arg, arg_type, desc = doc['Returns'][1]
230230
assert arg == ''
231231
assert arg_type == 'list of str'

numpydoc/xref.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ def make_xref(param_type, xref_aliases, xref_ignore):
108108
to fully qualified names that can be cross-referenced.
109109
xref_ignore : set or "all"
110110
A set containing words not to cross-reference. Instead of a set, the
111-
string 'all' can be given to ignore all unrecognized terms.
111+
string 'all' can be given to ignore all unrecognized terms.
112112
Unrecognized terms include those that are not in `xref_aliases` and
113113
are not already wrapped in a reST role.
114114

0 commit comments

Comments
 (0)