def test_xref_not_found_restructured(capsys: CapSys) -> None: """ When a link in an reStructedText docstring cannot be resolved, the reference and the line number of the link should be reported. However, currently the best we can do is report the starting line of the docstring instead. """ system = model.System() system.options.docformat = 'restructuredtext' mod = fromText(''' """ A test module. Link to limbo: `NoSuchName`. """ ''', modname='test', system=system) epydoc2stan.format_docstring(mod) captured = capsys.readouterr().out # TODO: Should actually be line 5, but I can't get docutils to fill in # the line number when it calls visit_title_reference(). # https://github.com/twisted/pydoctor/issues/237 assert captured == 'test:3: Cannot find link target for "NoSuchName"\n'
def _writeDocsFor(self, ob: model.Documentable) -> None: """ Trigger in memory rendering of the object. """ if not ob.isVisible: return epydoc2stan.format_docstring(ob) for o in ob.contents.values(): self._writeDocsFor(o)
def test_unknown_field_name(capsys: CapSys) -> None: mod = fromText(''' """ A test module. @zap: No such field. """ ''', modname='test') epydoc2stan.format_docstring(mod) captured = capsys.readouterr().out assert captured == "test:5: Unknown field 'zap'\n"
def test_func_param_duplicate(capsys: CapSys) -> None: """Warn when the same parameter is documented more than once.""" mod = fromText(''' def f(x, y): """ @param x: Actual documentation. @param x: Likely typo or copy-paste error. """ ''') epydoc2stan.format_docstring(mod.contents['f']) captured = capsys.readouterr().out assert captured == '<test>:5: Parameter "x" was already documented\n'
def test_func_missing_exception_type(capsys: CapSys) -> None: """Raise fields must include the exception type.""" mod = fromText(''' def f(x): """ @raise ValueError: If C{x} is rejected. @raise: On a blue moon. """ ''') epydoc2stan.format_docstring(mod.contents['f']) captured = capsys.readouterr().out assert captured == '<test>:5: Exception type missing\n'
def test_func_param_as_keyword(capsys: CapSys) -> None: """Warn when a parameter is documented as a @keyword.""" mod = fromText(''' def f(p, **kwargs): """ @keyword a: Advanced. @keyword b: Basic. @type b: Type for previously introduced keyword. @keyword p: A parameter, not a keyword. """ ''') epydoc2stan.format_docstring(mod.contents['f']) assert capsys.readouterr().out == '<test>:7: Parameter "p" is documented as keyword\n'
def test_unexpected_field_args(capsys: CapSys) -> None: """Warn when field arguments that should be empty aren't.""" mod = fromText(''' def get_it(): """ @return value: The thing you asked for, probably. @rtype value: Not a clue. """ ''') epydoc2stan.format_docstring(mod.contents['get_it']) captured = capsys.readouterr().out assert captured == "<test>:4: Unexpected argument in return field\n" \ "<test>:5: Unexpected argument in rtype field\n"
def test_missing_field_name(capsys: CapSys) -> None: mod = fromText(''' """ A test module. @ivar: Mystery variable. @type: str """ ''', modname='test') epydoc2stan.format_docstring(mod) captured = capsys.readouterr().out assert captured == "test:5: Missing field name in @ivar\n" \ "test:6: Missing field name in @type\n"
def test_func_no_such_arg(field: str, capsys: CapSys) -> None: """Warn about documented parameters that don't exist in the definition.""" mod = fromText(f''' def f(): """ This function takes no arguments... @{field} x: ...but it does document one. """ ''') epydoc2stan.format_docstring(mod.contents['f']) captured = capsys.readouterr().out assert captured == '<test>:6: Documented parameter "x" does not exist\n'
def test_func_missing_param_name(capsys: CapSys) -> None: """Param and type fields must include the name of the parameter.""" mod = fromText(''' def f(a, b): """ @param a: The first parameter. @param: The other one. @type: C{str} """ ''') epydoc2stan.format_docstring(mod.contents['f']) captured = capsys.readouterr().out assert captured == ('<test>:5: Parameter name missing\n' '<test>:6: Parameter name missing\n')
def test_multiple_types() -> None: mod = fromText(''' def f(a): """ @param a: it\'s a parameter! @type a: a pink thing! @type a: no, blue! aaaargh! """ class C: """ @ivar a: it\'s an instance var @type a: a pink thing! @type a: no, blue! aaaargh! """ class D: """ @cvar a: it\'s an instance var @type a: a pink thing! @type a: no, blue! aaaargh! """ class E: """ @cvar: missing name @type: name still missing """ ''') # basically "assert not fail": epydoc2stan.format_docstring(mod.contents['f']) epydoc2stan.format_docstring(mod.contents['C']) epydoc2stan.format_docstring(mod.contents['D']) epydoc2stan.format_docstring(mod.contents['E'])
def test_func_no_such_arg_warn_once(capsys: CapSys) -> None: """Warn exactly once about a param/type combination not existing.""" mod = fromText(''' def f(): """ @param x: Param first. @type x: Param first. @type y: Type first. @param y: Type first. """ ''') epydoc2stan.format_docstring(mod.contents['f']) captured = capsys.readouterr().out assert captured == ('<test>:4: Documented parameter "x" does not exist\n' '<test>:6: Documented parameter "y" does not exist\n')
def docstring2html(obj: model.Documentable) -> str: stan = epydoc2stan.format_docstring(obj) assert stan.tagName == 'div', stan # We strip off break lines for the sake of simplicity. return flatten(stan).replace('><', '>\n<').replace('<wbr></wbr>', '').replace( '<wbr>\n</wbr>', '')
def test_func_raise_missing_exception_type(capsys: CapSys) -> None: """When a C{raise} field is missing the exception type, a warning is logged and the HTML will list the exception type as unknown. """ mod = fromText(''' def f(x): """ @raise ValueError: If C{x} is rejected. @raise: On a blue moon. """ ''') func = mod.contents['f'] epydoc2stan.format_docstring(func) captured = capsys.readouterr().out assert captured == '<test>:5: Exception type missing\n' html = docstring2html(func).split('\n') assert '<span class="undocumented">Unknown exception</span>' in html
def test_inline_field_type(capsys: CapSys) -> None: """The C{type} field in a variable docstring updates the C{parsed_type} of the Attribute it documents. """ mod = fromText(''' a = 2 """ Variable documented by inline docstring. @type: number """ ''', modname='test') a = mod.contents['a'] assert isinstance(a, model.Attribute) epydoc2stan.format_docstring(a) assert isinstance(a.parsed_type, ParsedEpytextDocstring) assert str(unwrap(a.parsed_type)) == 'number' assert not capsys.readouterr().out
def test_inline_field_name(capsys: CapSys) -> None: """Warn if a name is given for a C{type} field in a variable docstring. A variable docstring only documents a single variable, so the name is redundant at best and misleading at worst. """ mod = fromText(''' a = 2 """ Variable documented by inline docstring. @type a: number """ ''', modname='test') a = mod.contents['a'] assert isinstance(a, model.Attribute) epydoc2stan.format_docstring(a) captured = capsys.readouterr().out assert captured == "test:5: Field in variable docstring should not include a name\n"
def test_xref_not_found_epytext(capsys: CapSys) -> None: """ When a link in an epytext docstring cannot be resolved, the reference and the line number of the link should be reported. """ mod = fromText(''' """ A test module. Link to limbo: L{NoSuchName}. """ ''', modname='test') epydoc2stan.format_docstring(mod) captured = capsys.readouterr().out assert captured == 'test:5: Cannot find link target for "NoSuchName"\n'
def test_func_arg_not_inherited(capsys: CapSys) -> None: """Do not warn when a subclass method lacks parameters that are documented in an inherited docstring. """ mod = fromText(''' class Base: def __init__(self, value): """ @param value: Preciousss. @type value: Gold. """ class Sub(Base): def __init__(self): super().__init__(1) ''') epydoc2stan.format_docstring(mod.contents['Base'].contents['__init__']) assert capsys.readouterr().out == '' epydoc2stan.format_docstring(mod.contents['Sub'].contents['__init__']) assert capsys.readouterr().out == ''
def get(self, ob, summary=False): if summary: return epydoc2stan.format_summary(ob) else: doc = epydoc2stan.format_docstring(ob) typ = epydoc2stan.type2stan(ob) if typ is None: return doc else: return [doc, ' (type: ', typ, ')']
def test_module_docformat(capsys: CapSys) -> None: """ Test if Module.docformat effectively override System.options.docformat """ system = model.System() system.options.docformat = 'plaintext' mod = fromText(''' """ Link to pydoctor: U{pydoctor <https://github.com/twisted/pydoctor>}. """ __docformat__ = "epytext" ''', modname='test_epy', system=system) epytext_output = epydoc2stan.format_docstring(mod) captured = capsys.readouterr().out assert not captured mod = fromText(''' """ Link to pydoctor: `pydoctor <https://github.com/twisted/pydoctor>`_. """ __docformat__ = "restructuredtext en" ''', modname='test_rst', system=system) restructuredtext_output = epydoc2stan.format_docstring(mod) captured = capsys.readouterr().out assert not captured assert 'href="https://github.com/twisted/pydoctor"' in flatten( epytext_output) assert 'href="https://github.com/twisted/pydoctor"' in flatten( restructuredtext_output)
def get(self, ob: model.Documentable, summary: bool = False) -> Tag: if summary: return epydoc2stan.format_summary(ob) else: return epydoc2stan.format_docstring(ob)
def docstring2html(obj: model.Documentable) -> str: stan = epydoc2stan.format_docstring(obj) assert stan.tagName == 'div', stan return flatten(stan.children).replace('><', '>\n<')
def docstring2html(docstring: model.Documentable) -> str: stan = epydoc2stan.format_docstring(docstring) return flatten(stan).replace('><', '>\n<')