from .dev_skip_test import dev_skip_test
from humpy_cytoolz import curry, identity, keyfilter, merge_with, valfilter
from humpy_cytoolz.utils import raises
import difflib
import humpy_cytoolz

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 `humpy_toolz` to `humpy_cytoolz`."""
    if hasattr(doc, '__doc__'):
        doc = doc.__doc__
    doc = doc.replace('humpy_toolz', 'humpy_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 humpy_toolz
    differ = difflib.Differ()
    toolz_dict = valfilter(isfrommod('humpy_toolz'), humpy_toolz.__dict__)
    cytoolz_dict = valfilter(isfrommod('humpy_cytoolz'), humpy_cytoolz.__dict__)
    toolz_dict = valfilter(lambda x: getattr(x, '__doc__', ''), toolz_dict)
    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():
        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)
            while diff and diff[0].startswith('+'):
                diff.pop(0)
            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.{} has a bad docstring:\n{}\n'.format(key, '\n'.join(fulldiff))

def test_get_in_doctest():
    raises(KeyError, lambda: humpy_cytoolz.get_in(['y'], {}, no_default=True))
