1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
|
import difflib
import cytoolz
from cytoolz import curry, identity, keyfilter, valfilter, merge_with
from cytoolz.utils import raises
from dev_skip_test import dev_skip_test
# `cytoolz` functions for which "# doctest: +SKIP" were added.
# This may have been done because the error message may not exactly match.
# The skipped tests should be added below with results and explanations.
skipped_doctests = ['get_in']
@curry
def isfrommod(modname, func):
mod = getattr(func, '__module__', '') or ''
return mod.startswith(modname) or 'toolz.functoolz.curry' in str(type(func))
def convertdoc(doc):
""" Convert docstring from `toolz` to `cytoolz`."""
if hasattr(doc, '__doc__'):
doc = doc.__doc__
doc = doc.replace('toolz', 'cytoolz')
doc = doc.replace('dictcytoolz', 'dicttoolz')
doc = doc.replace('funccytoolz', 'functoolz')
doc = doc.replace('itercytoolz', 'itertoolz')
doc = doc.replace('cytoolz.readthedocs', 'toolz.readthedocs')
return doc
@dev_skip_test
def test_docstrings_uptodate():
import toolz
differ = difflib.Differ()
# only consider items created in both `toolz` and `cytoolz`
toolz_dict = valfilter(isfrommod('toolz'), toolz.__dict__)
cytoolz_dict = valfilter(isfrommod('cytoolz'), cytoolz.__dict__)
# only test functions that have docstrings defined in `toolz`
toolz_dict = valfilter(lambda x: getattr(x, '__doc__', ''), toolz_dict)
# full API coverage should be tested elsewhere
toolz_dict = keyfilter(lambda x: x in cytoolz_dict, toolz_dict)
cytoolz_dict = keyfilter(lambda x: x in toolz_dict, cytoolz_dict)
d = merge_with(identity, toolz_dict, cytoolz_dict)
for key, (toolz_func, cytoolz_func) in d.items():
# only check if the new doctstring *contains* the expected docstring
# in Python < 3.13 the second line is indented, in 3.13+
# it is not, strip all lines to fudge it
toolz_doc = "\n".join((line.strip() for line in convertdoc(toolz_func).splitlines()))
cytoolz_doc = "\n".join((line.strip() for line in cytoolz_func.__doc__.splitlines()))
if toolz_doc not in cytoolz_doc:
diff = list(differ.compare(toolz_doc.splitlines(),
cytoolz_doc.splitlines()))
fulldiff = list(diff)
# remove additional lines at the beginning
while diff and diff[0].startswith('+'):
diff.pop(0)
# remove additional lines at the end
while diff and diff[-1].startswith('+'):
diff.pop()
def checkbad(line):
return (line.startswith('+') and
not ('# doctest: +SKIP' in line and
key in skipped_doctests))
if any(map(checkbad, diff)):
assert False, 'Error: cytoolz.%s has a bad docstring:\n%s\n' % (
key, '\n'.join(fulldiff))
def test_get_in_doctest():
# Original doctest:
# >>> get_in(['y'], {}, no_default=True)
# Traceback (most recent call last):
# ...
# KeyError: 'y'
# cytoolz result:
# KeyError:
raises(KeyError, lambda: cytoolz.get_in(['y'], {}, no_default=True))
|