Coder Social home page Coder Social logo

mkdocstrings / griffe Goto Github PK

View Code? Open in Web Editor NEW
252.0 6.0 37.0 6.08 MB

Signatures for entire Python programs. Extract the structure, the frame, the skeleton of your project, to generate API documentation or find breaking changes in your API.

Home Page: https://mkdocstrings.github.io/griffe

License: ISC License

Makefile 0.07% Python 98.98% Shell 0.93% Dockerfile 0.02%
python docs api breaking-changes parser signature mkdocstrings-collector

griffe's Introduction

Griffe

ci documentation pypi version gitpod gitter

Griffe logo, created by François Rozet <francois.rozet@outlook.com>

Signatures for entire Python programs. Extract the structure, the frame, the skeleton of your project, to generate API documentation or find breaking changes in your API.

Griffe, pronounced "grif" (/ɡʁif/), is a french word that means "claw", but also "signature" in a familiar way. "On reconnaît bien là sa griffe."

Installation

With pip:

pip install griffe

With pipx:

python3.8 -m pip install --user pipx
pipx install griffe

Usage

On the command line, pass the names of packages to the griffe dump command:

$ griffe dump httpx fastapi
{
  "httpx": {
    "name": "httpx",
    ...
  },
  "fastapi": {
    "name": "fastapi",
    ...
  }
}

See the Dumping data section for more examples.

Or pass a relative path to the griffe check command:

$ griffe check mypackage --verbose
mypackage/mymodule.py:10: MyClass.mymethod(myparam):
Parameter kind was changed:
  Old: positional or keyword
  New: keyword-only

For src layouts:

$ griffe check --search src mypackage --verbose
src/mypackage/mymodule.py:10: MyClass.mymethod(myparam):
Parameter kind was changed:
  Old: positional or keyword
  New: keyword-only

See the API breakage section for more examples.

With Python, loading a package:

import griffe

fastapi = griffe.load("fastapi")

Finding breaking changes:

import griffe

previous = griffe.load_git("mypackage", ref="0.2.0")
current = griffe.load("mypackage")

for breakage in griffe.find_breaking_changes(previous, current):
    ...

See the Loading data section for more examples.

Todo

  • Extensions
    • Post-processing extensions
    • Third-party libraries we could provide support for:
      • Django support
      • Marshmallow support
      • Pydantic support
  • Docstrings parsers
    • epydoc
    • New Markdown-based format? For graceful degradation
  • Serializer:
    • Flat JSON
  • API diff:
    • Mechanism to cache APIs? Should users version them, or store them somewhere (docs)?
    • Ability to return warnings (things that are not backward-compatibility-friendly)
    • List of things to consider for warnings
      • Multiple positional-or-keyword parameters
      • Public imports in public modules
      • Private things made public through imports/assignments
      • Too many public things? Generally annoying. Configuration?
    • Ability to compare two APIs to return breaking changes
    • List of things to consider for breaking changes
      • Changed position of positional only parameter
      • Changed position of positional or keyword parameter
      • Changed type of parameter
      • Changed type of public module attribute
      • Changed return type of a public function/method
      • Added parameter without a default value
      • Removed keyword-only parameter without a default value, without **kwargs to swallow it
      • Removed positional-only parameter without a default value, without *args to swallow it
      • Removed positional-or_keyword argument without a default value, without *args and **kwargs to swallow it
      • Removed public module/class/function/method/attribute
      • All of the previous even when parent is private (could be publicly imported or assigned somewhere), and later be smarter: public assign/import makes private things public!
      • Inheritance: removed, added or changed base that changes MRO

griffe's People

Contributors

antoined avatar ashwinvin avatar bandersen23 avatar blueglassblock avatar davfsa avatar fasterspeeding avatar francois-rozet avatar gabdug avatar georggi avatar gilfree avatar gpuligundla avatar has2k1 avatar jgarte avatar johnnoone avatar kevinmusgrave avatar machow avatar maxb2 avatar parafoxia avatar pawamoy avatar rodrigogiraoserrao avatar romain-intel avatar rudolfbyker avatar sisp avatar thatlittleboy avatar thomzoy avatar tlambert03 avatar viccie30 avatar willdasilva avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

griffe's Issues

docstrings/sphinx: Support "ignore __init__ summary" option

The mkdocstrings Python handler is able to merge __init__ methods docstrings into their classes' docstrings.
This is nice, but usually __init__ methods just have a summary like "Initialize this [CLASS]." which simply breaks the flow of the merged docstring, especially since it's usually followed by a Parameters section.

This option allows to ignore the summary (while keeping the correct line number in parsing warnings).

ignore_summary = (
ignore_init_summary # noqa: WPS222
and docstring.parent is not None
and docstring.parent.name == "__init__"
and docstring.parent.is_function
and docstring.parent.parent is not None
and docstring.parent.parent.is_class
)
if ignore_summary:
offset = 2
else:
offset = 0

docstrings/sphinx: Support cross-refs for types in "Returns" sections

Is your feature request related to a problem? Please describe.
The goal is to have a common set of features between all parsers.

Describe the solution you'd like
The Sphinx parser should be able to parse the types in "Returns" section in order to enable automatic cross-references.

from griffe.docstrings.utils import parse_annotation

# annotation is a string
annotation = parse_annotation(annotation, docstring)
# annotation is unchanged, or becomes a Name or Expression! cross-refs enabled

docstrings/sphinx: Support "Receives" sections

Is your feature request related to a problem? Please describe.
The goal is to have a common set of features between all parsers.

Describe the solution you'd like
The Sphinx parser should be able to parse "Receives" sections, if it makes any sense.

Ignore `__doc__` from parent classes

Is your feature request related to a problem? Please describe.
Currently Griffe will fall-back to extracting docstrings from the __doc__ attribute if it cannot obtain them from the source file. When it does so, it will make use of the __doc__ attribute of parent classes if the derived class does not have a docstring. This frequently leads to misleading documentation.

For example, if you create a class that inherits from numbers.Real, your class will have the following text picked up by Griffe unless you define a docstring:

>>> print(numbers.Real.__doc__)
To Complex, Real adds the operations that work on real numbers.

    In short, those are: a conversion to float, trunc(), divmod,
    %, <, <=, >, and >=.

    Real also provides defaults for the derived operations.

Describe the solution you'd like
Instead of using getattr(x, '__doc__'), Griffe can directly access the members of the class it is gathering docstrings from with x.__dict__['__doc__'].

This would make the behaviour more consistent with how Griffe extracts docstrings from regular Python modules, as for those it does not use the docstring from parent classes at all.

docstrings/sphinx: Support cross-refs for types in "Other Parameters" sections

Is your feature request related to a problem? Please describe.
The goal is to have a common set of features between all parsers.

Describe the solution you'd like
The Sphinx parser should be able to parse the types in "Other Parameters" section in order to enable automatic cross-references.

from griffe.docstrings.utils import parse_annotation

# annotation is a string
annotation = parse_annotation(annotation, docstring)
# annotation is unchanged, or becomes a Name or Expression! cross-refs enabled

docstrings/numpy: Support cross-refs for types in "Warns" sections

Is your feature request related to a problem? Please describe.
The goal is to have a common set of features between all parsers.

Describe the solution you'd like
The Numpy parser should be able to parse the types in "Warns" section in order to enable automatic cross-references.

from griffe.docstrings.utils import parse_annotation

# annotation is a string
annotation = parse_annotation(annotation, docstring)
# annotation is unchanged, or becomes a Name or Expression! cross-refs enabled

docstrings/numpy: Support cross-refs for types in "Receives" sections

Is your feature request related to a problem? Please describe.
The goal is to have a common set of features between all parsers.

Describe the solution you'd like
The Numpy parser should be able to parse the types in "Receives" section in order to enable automatic cross-references.

from griffe.docstrings.utils import parse_annotation

# annotation is a string
annotation = parse_annotation(annotation, docstring)
# annotation is unchanged, or becomes a Name or Expression! cross-refs enabled

docstrings/sphinx: Support "Examples" sections

Is your feature request related to a problem? Please describe.
The goal is to have a common set of features between all parsers.

Describe the solution you'd like
The Sphinx parser should be able to parse "Examples" sections, if it makes any sense.

docstrings/sphinx: Support cross-refs for types in "Parameters" sections

Is your feature request related to a problem? Please describe.
The goal is to have a common set of features between all parsers.

Describe the solution you'd like
The Sphinx parser should be able to parse the types in "Parameters" section in order to enable automatic cross-references.

from griffe.docstrings.utils import parse_annotation

# annotation is a string
annotation = parse_annotation(annotation, docstring)
# annotation is unchanged, or becomes a Name or Expression! cross-refs enabled

docstrings/numpy: Support cross-refs for types in "Parameters" sections

Is your feature request related to a problem? Please describe.
The goal is to have a common set of features between all parsers.

Describe the solution you'd like
The Numpy parser should be able to parse the types in "Parameters" section in order to enable automatic cross-references.

from griffe.docstrings.utils import parse_annotation

# annotation is a string
annotation = parse_annotation(annotation, docstring)
# annotation is unchanged, or becomes a Name or Expression! cross-refs enabled

griffe.exceptions.AliasResolutionError: Could not resolve django.db.models.fields.json.JSONField

Describe the bug
The following exception is raised:

ERROR    -  Error building page 'reference/selectors/models.md': Could not resolve django.db.models.fields.json.JSONField
Traceback (most recent call last):
  File "/myproject/.venv/lib/python3.10/site-packages/mkdocs_autorefs/plugin.py", line 88, in get_item_url
    url = self._url_map[identifier]
KeyError: 'django.db.models.JSONField'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/myproject/.venv/lib/python3.10/site-packages/griffe/dataclasses.py", line 864, in resolve_target
    resolved = self.modules_collection[self.target_path]
  File "/myproject/.venv/lib/python3.10/site-packages/griffe/mixins.py", line 26, in __getitem__
    return self.members[parts[0]][parts[1]]  # type: ignore[attr-defined]
  File "/myproject/.venv/lib/python3.10/site-packages/griffe/mixins.py", line 26, in __getitem__
    return self.members[parts[0]][parts[1]]  # type: ignore[attr-defined]
  File "/myproject/.venv/lib/python3.10/site-packages/griffe/mixins.py", line 26, in __getitem__
    return self.members[parts[0]][parts[1]]  # type: ignore[attr-defined]
  [Previous line repeated 2 more times]
KeyError: 'json'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/myproject/.venv/bin/mkdocs", line 8, in <module>
    sys.exit(cli())
  File "/myproject/.venv/lib/python3.10/site-packages/click/core.py", line 1128, in __call__
    return self.main(*args, **kwargs)
  File "/myproject/.venv/lib/python3.10/site-packages/click/core.py", line 1053, in main
    rv = self.invoke(ctx)
  File "/myproject/.venv/lib/python3.10/site-packages/click/core.py", line 1659, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/myproject/.venv/lib/python3.10/site-packages/click/core.py", line 1395, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/myproject/.venv/lib/python3.10/site-packages/click/core.py", line 754, in invoke
    return __callback(*args, **kwargs)
  File "/myproject/.venv/lib/python3.10/site-packages/mkdocs/__main__.py", line 177, in serve_command
    serve.serve(dev_addr=dev_addr, livereload=livereload, **kwargs)
  File "/myproject/.venv/lib/python3.10/site-packages/mkdocs/commands/serve.py", line 54, in serve
    config = builder()
  File "/myproject/.venv/lib/python3.10/site-packages/mkdocs/commands/serve.py", line 49, in builder
    build(config, live_server=live_server, dirty=dirty)
  File "/myproject/.venv/lib/python3.10/site-packages/mkdocs/commands/build.py", line 314, in build
    _build_page(file.page, config, doc_files, nav, env, dirty)
  File "/myproject/.venv/lib/python3.10/site-packages/mkdocs/commands/build.py", line 220, in _build_page
    output = config['plugins'].run_event(
  File "/myproject/.venv/lib/python3.10/site-packages/mkdocs/plugins.py", line 102, in run_event
    result = method(item, **kwargs)
  File "/myproject/.venv/lib/python3.10/site-packages/mkdocs_autorefs/plugin.py", line 197, in on_post_page
    fixed_output, unmapped = fix_refs(output, url_mapper)
  File "/myproject/.venv/lib/python3.10/site-packages/mkdocs_autorefs/references.py", line 186, in fix_refs
    html = AUTO_REF_RE.sub(fix_ref(url_mapper, unmapped), html)
  File "/myproject/.venv/lib/python3.10/site-packages/mkdocs_autorefs/references.py", line 156, in inner
    url = url_mapper(unescape(identifier))
  File "/myproject/.venv/lib/python3.10/site-packages/mkdocs_autorefs/plugin.py", line 94, in get_item_url
    new_identifiers = fallback(identifier)
  File "/myproject/.venv/lib/python3.10/site-packages/mkdocstrings/handlers/base.py", line 408, in get_anchors
    anchors = handler.renderer.get_anchors(handler.collector.collect(identifier, fallback_config))
  File "/myproject/.venv/lib/python3.10/site-packages/mkdocstrings_handlers/python/collector.py", line 82, in collect
    if not just_loaded and doc_object.docstring is not None:
  File "/myproject/.venv/lib/python3.10/site-packages/griffe/dataclasses.py", line 764, in __getattr__
    attr = getattr(self.target, name)
  File "/myproject/.venv/lib/python3.10/site-packages/griffe/dataclasses.py", line 841, in target
    self.resolve_target()
  File "/myproject/.venv/lib/python3.10/site-packages/griffe/dataclasses.py", line 866, in resolve_target
    raise AliasResolutionError(self.target_path) from error
griffe.exceptions.AliasResolutionError: Could not resolve django.db.models.fields.json.JSONField

To Reproduce

Try to process the following code using mkdocstrings and griffe:
Raises exception griffe.exceptions.AliasResolutionError:

from django.db import models

class CustomField(models.JSONField):
   ...

Workaround

from django.db.models.fields.json import JSONField

class CustomField(JSONField):
   ...

Expected behavior

Should be processed normally

System (please complete the following information):

  • griffe version: 0.11.6
  • Python version: 3.10
  • OS: Linux

Additional context

https://github.com/django/django/blob/main/django/db/models/__init__.py

Infer docstring style

It would be nice if we could simply infer the doc string style automatically and choose the appropriate
parser. This would especially be useful when:

  • the code is the result of combining code from other projects using different doc styles
  • you are changing the official doc-string style and don't want to have to convert all your strings at once
  • you are subclassing from another library using a different doc string format and want to include inherited members

docstrings/sphinx: Support "trim_doctest_flags" option

This trim_doctest_flags option allows the user to remove doctest flags like # doctest: +FLAG and <BLANKLINE>, present in example snippets within docstrings, from the parsed output.
E.g.

def f(x: int) -> int:
    """Test function.

    Example:
        We want to skip the following test.
        >>> 1 + 1 == 3  # doctest: +SKIP
        True
        And then a few more examples here:
        >>> print("a\\n\\nb")
        a
        <BLANKLINE>
        b
        >>> 1 + 1 == 2  # doctest: +SKIP
        >>> print(list(range(1, 100)))    # doctest: +ELLIPSIS
        [1, 2, ..., 98, 99]
    """
    return x

This is default behaviour in Sphinx.
See original discussion / feature request on mkdocstrings/mkdocstrings#386.

The idea is to emulate this behaviour for this sphinx parser in griffe.

Pre-requisite / blocker for this issue seems to be #7 .

ValueError when using griffe as a docstring parser

Describe the bug

When using Griffe as a docstring-parsing library according to https://mkdocstrings.github.io/griffe/usage/#using-griffe-as-a-docstring-parsing-library , we sometimes get ValueError at

https://github.com/mkdocstrings/griffe/blob/master/src/griffe/dataclasses.py#L497

... which is caused by the warning method

https://github.com/mkdocstrings/griffe/blob/master/src/griffe/docstrings/utils.py#L37

... which is called from

https://github.com/mkdocstrings/griffe/blob/master/src/griffe/docstrings/google.py#L189

... when an annotation is missing.

To Reproduce

Run this:

from griffe.dataclasses import Docstring, Function, Parameters, Parameter
from griffe.docstrings.google import parse

if __name__ == "__main__":
    parsed_docstring = parse(
        Docstring(
            value="""\
A function.

Args:
    a: Whatever

Returns:
    Nothing.
""",
            lineno=1,
            parent=Function(
                name="foo",
                parameters=Parameters(
                    Parameter(
                        name="a",
                        annotation=None,
                        default="5",
                    )
                ),
            ),
        )
    )

Expected behavior
No error, just the usual warning. The warning need not contain the file path if there is no file path.

System (please complete the following information):

  • griffe version: 0.13.0
  • Python version: 3.7
  • OS: Windows

Additional context
Add any other context about the problem here.

docstrings/sphinx: Support cross-refs for types in "Receives" sections

Is your feature request related to a problem? Please describe.
The goal is to have a common set of features between all parsers.

Describe the solution you'd like
The Sphinx parser should be able to parse the types in "Receives" section in order to enable automatic cross-references.

from griffe.docstrings.utils import parse_annotation

# annotation is a string
annotation = parse_annotation(annotation, docstring)
# annotation is unchanged, or becomes a Name or Expression! cross-refs enabled

docstrings/numpy: Support cross-refs for types in "Returns" sections

Is your feature request related to a problem? Please describe.
The goal is to have a common set of features between all parsers.

Describe the solution you'd like
The Numpy parser should be able to parse the types in "Returns" section in order to enable automatic cross-references.

from griffe.docstrings.utils import parse_annotation

# annotation is a string
annotation = parse_annotation(annotation, docstring)
# annotation is unchanged, or becomes a Name or Expression! cross-refs enabled

docstrings/sphinx: Support "Other Parameters" sections

Is your feature request related to a problem? Please describe.
The goal is to have a common set of features between all parsers.

Describe the solution you'd like
The Sphinx parser should be able to parse "Other Parameters" sections, if it makes any sense.

docstrings/sphinx: Support cross-refs for types in "Warns" sections

Is your feature request related to a problem? Please describe.
The goal is to have a common set of features between all parsers.

Describe the solution you'd like
The Sphinx parser should be able to parse the types in "Warns" section in order to enable automatic cross-references.

from griffe.docstrings.utils import parse_annotation

# annotation is a string
annotation = parse_annotation(annotation, docstring)
# annotation is unchanged, or becomes a Name or Expression! cross-refs enabled

docstrings/numpy: Support cross-refs for types in "Raises" sections

Is your feature request related to a problem? Please describe.
The goal is to have a common set of features between all parsers.

Describe the solution you'd like
The Numpy parser should be able to parse the types in "Raises" section in order to enable automatic cross-references.

from griffe.docstrings.utils import parse_annotation

# annotation is a string
annotation = parse_annotation(annotation, docstring)
# annotation is unchanged, or becomes a Name or Expression! cross-refs enabled

docstrings/sphinx: Support cross-refs for types in "Attributes" sections

Is your feature request related to a problem? Please describe.
The goal is to have a common set of features between all parsers.

Describe the solution you'd like
The Sphinx parser should be able to parse the types in "Attributes" section in order to enable automatic cross-references.

from griffe.docstrings.utils import parse_annotation

# annotation is a string
annotation = parse_annotation(annotation, docstring)
# annotation is unchanged, or becomes a Name or Expression! cross-refs enabled

docstrings/sphinx: Support "Yields" sections

Is your feature request related to a problem? Please describe.
The goal is to have a common set of features between all parsers.

Describe the solution you'd like
The Sphinx parser should be able to parse "Yields" sections, if it makes any sense.

Infinite loop while parsing some docstrings with google

Describe the bug
Trying to google-parse this string loops indefinitely:

Python Markdown

A Python implementation of John Gruber's Markdown.

Documentation: https://python-markdown.github.io/
GitHub: https://github.com/Python-Markdown/markdown/
PyPI: https://pypi.org/project/Markdown/

Started by Manfred Stienstra (http://www.dwerg.net/).
Maintained for a few years by Yuri Takhteyev (http://www.freewisdom.org).
Currently maintained by Waylan Limberg (https://github.com/waylan),
Dmitry Shachnev (https://github.com/mitya57) and Isaac Muse (https://github.com/facelessuser).

Copyright 2007-2018 The Python Markdown Project (v. 1.7 and later)
Copyright 2004, 2005, 2006 Yuri Takhteyev (v. 0.2-1.6b)
Copyright 2004 Manfred Stienstra (the original version)

License: BSD (see LICENSE.md for details).

Expected behavior
No infinite loop.

Create a logo

Call to freelancers! I would like a logo for griffe. What I have in mind is this: black and white, thick lines, one or two vulture claws grabbing "GRIFFE" from the sky, with the blinding light of the sun behind them.

For the light, I was thinking using straight lines like this:
image
But there are probably other ways to give this effect of high contrast and strong light.

*args and **kwargs lines in Numpydoc parameter sections fail to parse

Describe the bug
Documentation for *args and **kwargs (as according to https://numpydoc.readthedocs.io/en/latest/format.html#parameters) fails to parse in Numpydoc Parameter and Other Parameter sections

To Reproduce
Trying to parse a docstring with the following docstring through numpydocstring

Parameters
------------
*args : typing.Any
    Pass through
**kwargs : typing.Any
    Pass through

Leads to the following being logged when using the versions specified below

WARNING  -  griffe: alluka\abc.py:461: Could not parse line '*args : typing.Any'
WARNING  -  griffe: alluka\abc.py:461: Could not parse line '**kwargs : typing.Any'
WARNING  -  griffe: alluka\abc.py:461: Empty parameters section at line 4

being logged

Expected behavior
These lines shouldn't fail to parse

Screenshots
If applicable, add screenshots to help explain your problem.

System (please complete the following information):
griffe == 0.12.5
mkdocstrings-python==0.6.2
py ver 3.10
OS: Win 12 - 1

Additional context
Add any other context about the problem here.

docstrings/numpy: Support cross-refs for types in "Other Parameters" sections

Is your feature request related to a problem? Please describe.
The goal is to have a common set of features between all parsers.

Describe the solution you'd like
The Numpy parser should be able to parse the types in "Other Parameters" section in order to enable automatic cross-references.

from griffe.docstrings.utils import parse_annotation

# annotation is a string
annotation = parse_annotation(annotation, docstring)
# annotation is unchanged, or becomes a Name or Expression! cross-refs enabled

docstrings/sphinx: Support cross-refs for types in "Yields" sections

Is your feature request related to a problem? Please describe.
The goal is to have a common set of features between all parsers.

Describe the solution you'd like
The Sphinx parser should be able to parse the types in "Yields" section in order to enable automatic cross-references.

from griffe.docstrings.utils import parse_annotation

# annotation is a string
annotation = parse_annotation(annotation, docstring)
# annotation is unchanged, or becomes a Name or Expression! cross-refs enabled

Examples in Google style do not show

Edited. This issue has been solved by myself. Dear developer, just see my second comment below please, and confirm whether I am correct, or whether there is a better way. Then we can close this issue.

Describe the bug
I used the google style to write my python docstrings. The "examples" section is not rendered by mkdocstrings, while other sections such as "Parameters" and "Returns" work well.

To Reproduce
Just write a docstring like:

def foo():
    """
    Examples:
        We can print something:
        >>> print('foo')
        'foo'
    """

Expected behavior
I expect that the "examples" section is rendered, just like the previous python handler's behavior.

Screenshots
You can see nothing shown below "Examples".
image

System (please complete the following information):

  • griffe version: 0.12.6
  • Python version: 3.9.7
  • OS: MacOS 12.2.1

Additional context
I tried to debug that. If I change the content in templates/python/material/_base/docstring/examples.html from

{{ log.debug() }}
<p><strong>{{ section.title or "Examples:" }}</strong></p>
{% for section_type, sub_section in section.value %}
  {% if section_type == "markdown" %}
    {{ sub_section|convert_markdown(heading_level, html_id) }}
  {% elif section_type == "examples" %}
    {{ sub_section|highlight(language="python", linenums=False) }}
  {% endif %}
{% endfor %}

to

{{ log.debug() }}
<p><strong>{{ section.title or "Examples:" }}</strong></p>
{% for section_type, sub_section in section.value %}
    {{ sub_section|highlight(language="python", linenums=False) }}
{% endfor %}

Then the section will be rendered but the markdown text is also rendered as code:
image

Therefore, I think there may be something wrong with {% if section_type == "markdown" %} or {% elif section_type == "examples" %}, making the value always "False". To confirm this, I add {{ section_type}} and {{ section_type == "examples"}} to the for loop, and then:
image
You can see that the section_type is DocstringSectionKind.examples, and {{ section_type == "examples"}} is False. I then tried {{ section_type == "DocstringSectionKind.examples"}}, but it is still False.

Recursion error when running `griffe griffe`

To reproduce, install griffe version 0.8.1.dev16+g580251b (pip install . on commit 580251b550f952d72bf550ea26a1c09660761164 - currently the head of the master branch), then run griffe griffe. This results in a recursion error.

The following is the error message, with the repeating section manually truncated:

INFO       Loading package griffe
Traceback (most recent call last):
  File "/home/will/.pyenv/versions/workshop/bin/griffe", line 8, in <module>
    sys.exit(main())
  File "/home/will/.pyenv/versions/3.9.6/envs/workshop/lib/python3.9/site-packages/griffe/cli.py", line 234, in main
    packages = _load_packages(opts.packages, extensions, search, opts.docstyle, opts.docopts)
  File "/home/will/.pyenv/versions/3.9.6/envs/workshop/lib/python3.9/site-packages/griffe/cli.py", line 97, in _load_packages
    if not loader.follow_aliases(obj, only_exported=False, only_known_modules=True):
  File "/home/will/.pyenv/versions/3.9.6/envs/workshop/lib/python3.9/site-packages/griffe/loader.py", line 240, in follow_aliases
    member.resolve_target()  # type: ignore[union-attr]
  File "/home/will/.pyenv/versions/3.9.6/envs/workshop/lib/python3.9/site-packages/griffe/dataclasses.py", line 810, in resolve_target
    self._target = self.modules_collection[self._target_path]
  File "/home/will/.pyenv/versions/3.9.6/envs/workshop/lib/python3.9/site-packages/griffe/mixins.py", line 26, in __getitem__
    return self.members[parts[0]][parts[1]]  # type: ignore[attr-defined]
  File "/home/will/.pyenv/versions/3.9.6/envs/workshop/lib/python3.9/site-packages/griffe/mixins.py", line 26, in __getitem__
    return self.members[parts[0]][parts[1]]  # type: ignore[attr-defined]
  File "/home/will/.pyenv/versions/3.9.6/envs/workshop/lib/python3.9/site-packages/griffe/dataclasses.py", line 725, in __getitem__
    return self.target[key]
  File "/home/will/.pyenv/versions/3.9.6/envs/workshop/lib/python3.9/site-packages/griffe/dataclasses.py", line 790, in target
    self.resolve_target()
  File "/home/will/.pyenv/versions/3.9.6/envs/workshop/lib/python3.9/site-packages/griffe/dataclasses.py", line 810, in resolve_target
[...]
  File "/home/will/.pyenv/versions/3.9.6/envs/workshop/lib/python3.9/site-packages/griffe/dataclasses.py", line 810, in resolve_target
    self._target = self.modules_collection[self._target_path]
  File "/home/will/.pyenv/versions/3.9.6/envs/workshop/lib/python3.9/site-packages/griffe/mixins.py", line 26, in __getitem__
    return self.members[parts[0]][parts[1]]  # type: ignore[attr-defined]
  File "/home/will/.pyenv/versions/3.9.6/envs/workshop/lib/python3.9/site-packages/griffe/mixins.py", line 26, in __getitem__
    return self.members[parts[0]][parts[1]]  # type: ignore[attr-defined]
  File "/home/will/.pyenv/versions/3.9.6/envs/workshop/lib/python3.9/site-packages/griffe/dataclasses.py", line 725, in __getitem__
    return self.target[key]
  File "/home/will/.pyenv/versions/3.9.6/envs/workshop/lib/python3.9/site-packages/griffe/dataclasses.py", line 790, in target
    self.resolve_target()
  File "/home/will/.pyenv/versions/3.9.6/envs/workshop/lib/python3.9/site-packages/griffe/dataclasses.py", line 810, in resolve_target
    self._target = self.modules_collection[self._target_path]
  File "/home/will/.pyenv/versions/3.9.6/envs/workshop/lib/python3.9/site-packages/griffe/mixins.py", line 26, in __getitem__
    return self.members[parts[0]][parts[1]]  # type: ignore[attr-defined]
  File "/home/will/.pyenv/versions/3.9.6/envs/workshop/lib/python3.9/site-packages/griffe/mixins.py", line 26, in __getitem__
    return self.members[parts[0]][parts[1]]  # type: ignore[attr-defined]
  File "/home/will/.pyenv/versions/3.9.6/envs/workshop/lib/python3.9/site-packages/griffe/dataclasses.py", line 725, in __getitem__
    return self.target[key]
  File "/home/will/.pyenv/versions/3.9.6/envs/workshop/lib/python3.9/site-packages/griffe/dataclasses.py", line 790, in target
    self.resolve_target()
  File "/home/will/.pyenv/versions/3.9.6/envs/workshop/lib/python3.9/site-packages/griffe/dataclasses.py", line 810, in resolve_target
    self._target = self.modules_collection[self._target_path]
  File "/home/will/.pyenv/versions/3.9.6/envs/workshop/lib/python3.9/site-packages/griffe/mixins.py", line 26, in __getitem__
    return self.members[parts[0]][parts[1]]  # type: ignore[attr-defined]
  File "/home/will/.pyenv/versions/3.9.6/envs/workshop/lib/python3.9/site-packages/griffe/mixins.py", line 26, in __getitem__
    return self.members[parts[0]][parts[1]]  # type: ignore[attr-defined]
  File "/home/will/.pyenv/versions/3.9.6/envs/workshop/lib/python3.9/site-packages/griffe/dataclasses.py", line 725, in __getitem__
    return self.target[key]
  File "/home/will/.pyenv/versions/3.9.6/envs/workshop/lib/python3.9/site-packages/griffe/dataclasses.py", line 790, in target
    self.resolve_target()
  File "/home/will/.pyenv/versions/3.9.6/envs/workshop/lib/python3.9/site-packages/griffe/dataclasses.py", line 810, in resolve_target
    self._target = self.modules_collection[self._target_path]
RecursionError: maximum recursion depth exceeded

This error does not occur on version 0.8.0, which has been published to PyPI, but instead a key error is raised on that version when running griffe griffe. Given that 0.8.0 is an older version, I won't create an issue for it unless you'd like me to.

docstrings/numpy: Support cross-refs for types in "Attributes" sections

Is your feature request related to a problem? Please describe.
The goal is to have a common set of features between all parsers.

Describe the solution you'd like
The Numpy parser should be able to parse the types in "Attributes" section in order to enable automatic cross-references.

from griffe.docstrings.utils import parse_annotation

# annotation is a string
annotation = parse_annotation(annotation, docstring)
# annotation is unchanged, or becomes a Name or Expression! cross-refs enabled

Add labels/properties to doc-heading

Is your feature request related to a problem? Please describe.
Previous python handler can add properties of a method (e.g., "staticmethod", "property", "readonly") after the method's signature, but it seems that griffe hasn't have one. Although there is a template html file called "labels.html", which does exactly the same thing as the previous template "properties.html", it is not operational.

I also notice that in the TODO list of Griffe, the first item is "labels". I'm not sure whether that "labels" is what this feature request is asking for. If so, this issue could be closed, and we can just wait for the new feature to be released. Thank you!

docstrings/numpy: Support "ignore __init__ summary" option

The mkdocstrings Python handler is able to merge __init__ methods docstrings into their classes' docstrings.
This is nice, but usually __init__ methods just have a summary like "Initialize this [CLASS]." which simply breaks the flow of the merged docstring, especially since it's usually followed by a Parameters section.

This option allows to ignore the summary (while keeping the correct line number in parsing warnings).

ignore_summary = (
ignore_init_summary # noqa: WPS222
and docstring.parent is not None
and docstring.parent.name == "__init__"
and docstring.parent.is_function
and docstring.parent.parent is not None
and docstring.parent.parent.is_class
)
if ignore_summary:
offset = 2
else:
offset = 0

docstrings/sphinx: Support cross-refs for types in "Raises" sections

Is your feature request related to a problem? Please describe.
The goal is to have a common set of features between all parsers.

Describe the solution you'd like
The Sphinx parser should be able to parse the types in "Raises" section in order to enable automatic cross-references.

from griffe.docstrings.utils import parse_annotation

# annotation is a string
annotation = parse_annotation(annotation, docstring)
# annotation is unchanged, or becomes a Name or Expression! cross-refs enabled

Static-only objects are included in wildcards expansions

Describe the bug
Currently, expanding a wildcard will include members that are only "statically" present.
More specifically: members that are defined or imported under an if TYPE_CHECKING or if False condition.
This is problematic because this can lead to cyclic aliases.

To Reproduce
Steps to reproduce the behavior:

# package/module_a.py
from typing import TYPE_CHECKING

if TYPE_CHECKING:  # always false
    from package.module_b import CONST
# package/__init__.py
from .module_a import *

At runtime, package would definitely not have CONST in its members.

Expected behavior
These "static-only" objects should not be included in wildcards expansions.

Additional context
mkdocstrings/mkdocstrings#382
Maybe an other way to fix that would be to better handle duplicate members.
But that depends on the order we add expanded wildcard's members...

Computing MRO

Hi @pawamoy,

I've had time to start working on pydocspec again.

Here is the code I used to compute the MRO. The algorithm is encapsulated in a generic class such that we can use that with any kind of objects representing a class.

https://github.com/tristanlatr/pydocspec/blob/main/pydocspec/mro.py

The concrete class: https://github.com/tristanlatr/pydocspec/blob/fd25e4eaf47de6fca6706283296316a6ae515955/pydocspec/processor.py#L117

Here are the tests: https://github.com/tristanlatr/pydocspec/blob/main/pydocspec/test/test_mro.py

Hope this helps.

PS: there is a lot of overlap between griffe and pydocspec.. maybe there is something to do about it?

docstrings/numpy: Support cross-refs for types in "Yields" sections

Is your feature request related to a problem? Please describe.
The goal is to have a common set of features between all parsers.

Describe the solution you'd like
The Numpy parser should be able to parse the types in "Yields" section in order to enable automatic cross-references.

from griffe.docstrings.utils import parse_annotation

# annotation is a string
annotation = parse_annotation(annotation, docstring)
# annotation is unchanged, or becomes a Name or Expression! cross-refs enabled

docstrings/sphinx: Support "Warns" sections

Is your feature request related to a problem? Please describe.
The goal is to have a common set of features between all parsers.

Describe the solution you'd like
The Sphinx parser should be able to parse "Warns" sections, if it makes any sense.

docstrings/sphinx: Support "Deprecated" sections

Is your feature request related to a problem? Please describe.
The goal is to have a common set of features between all parsers.

Describe the solution you'd like
The Sphinx parser should be able to parse "Deprecated" sections, if it makes any sense.

Could not resolve abc.abstractmethod

Describe the bug
griffe appears to have an issue with abc.abstractmethod.

To Reproduce
I'm attempting to generate documentation using the experimental python handler of mkdocstrings on code that includes abstract methods. The source includes a class definition similar to:

from abc import abstractmethod
from typing_extensions import Protocol

class A(Protocol):
    @property
    @abstractmethod
    def prop(self):
        raise NotImplementedError

    @prop.setter
    @abstractmethod
    def prop(self, value):
        raise NotImplementedError

I believe this is a minimally reproducible example (if not the actual file is here). It produces the following error message:

ERROR    -  Error reading page 'reference.md': Could not resolve abc.abstractmethod
Traceback (most recent call last):
  File "c:\users\cory\appdata\local\programs\python\python38\lib\site-packages\griffe\dataclasses.py", line 859, in resolve_target
    resolved = self.modules_collection[self.target_path]
  File "c:\users\cory\appdata\local\programs\python\python38\lib\site-packages\griffe\mixins.py", line 26, in __getitem__
    return self.members[parts[0]][parts[1]]  # type: ignore[attr-defined]
KeyError: 'abc'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "c:\users\cory\appdata\local\programs\python\python38\lib\runpy.py", line 194, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "c:\users\cory\appdata\local\programs\python\python38\lib\runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "C:\Users\Cory\AppData\Local\Programs\Python\Python38\Scripts\mkdocs.exe\__main__.py", line 7, in <module>
  File "c:\users\cory\appdata\local\programs\python\python38\lib\site-packages\click\core.py", line 1128, in __call__
    return self.main(*args, **kwargs)
  File "c:\users\cory\appdata\local\programs\python\python38\lib\site-packages\click\core.py", line 1053, in main
    rv = self.invoke(ctx)
  File "c:\users\cory\appdata\local\programs\python\python38\lib\site-packages\click\core.py", line 1659, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "c:\users\cory\appdata\local\programs\python\python38\lib\site-packages\click\core.py", line 1395, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "c:\users\cory\appdata\local\programs\python\python38\lib\site-packages\click\core.py", line 754, in invoke
    return __callback(*args, **kwargs)
  File "c:\users\cory\appdata\local\programs\python\python38\lib\site-packages\mkdocs\__main__.py", line 177, in serve_command
    serve.serve(dev_addr=dev_addr, livereload=livereload, **kwargs)
  File "c:\users\cory\appdata\local\programs\python\python38\lib\site-packages\mkdocs\commands\serve.py", line 54, in serve
    config = builder()
  File "c:\users\cory\appdata\local\programs\python\python38\lib\site-packages\mkdocs\commands\serve.py", line 49, in builder
    build(config, live_server=live_server, dirty=dirty)
  File "c:\users\cory\appdata\local\programs\python\python38\lib\site-packages\mkdocs\commands\build.py", line 292, in build
    _populate_page(file.page, config, files, dirty)
  File "c:\users\cory\appdata\local\programs\python\python38\lib\site-packages\mkdocs\commands\build.py", line 174, in _populate_page
    page.render(config, files)
  File "c:\users\cory\appdata\local\programs\python\python38\lib\site-packages\mkdocs\structure\pages.py", line 174, in render
    self.content = md.convert(self.markdown)
  File "c:\users\cory\appdata\local\programs\python\python38\lib\site-packages\markdown\core.py", line 264, in convert
    root = self.parser.parseDocument(self.lines).getroot()
  File "c:\users\cory\appdata\local\programs\python\python38\lib\site-packages\markdown\blockparser.py", line 90, in parseDocument
    self.parseChunk(self.root, '\n'.join(lines))
  File "c:\users\cory\appdata\local\programs\python\python38\lib\site-packages\markdown\blockparser.py", line 105, in parseChunk
    self.parseBlocks(parent, text.split('\n\n'))
  File "c:\users\cory\appdata\local\programs\python\python38\lib\site-packages\markdown\blockparser.py", line 123, in parseBlocks
    if processor.run(parent, blocks) is not False:
  File "c:\users\cory\appdata\local\programs\python\python38\lib\site-packages\mkdocstrings\extension.py", line 120, in run
    html, handler, data = self._process_block(identifier, block, heading_level)
  File "c:\users\cory\appdata\local\programs\python\python38\lib\site-packages\mkdocstrings\extension.py", line 199, in _process_block
    rendered = handler.renderer.render(data, rendering)
  File "c:\users\cory\appdata\local\programs\python\python38\lib\site-packages\mkdocstrings_handlers\python\renderer.py", line 124, in render
    return template.render(
  File "c:\users\cory\appdata\local\programs\python\python38\lib\site-packages\jinja2\environment.py", line 1291, in render
    self.environment.handle_exception()
  File "c:\users\cory\appdata\local\programs\python\python38\lib\site-packages\jinja2\environment.py", line 925, in handle_exception
    raise rewrite_traceback_stack(source=source)
  File "c:\users\cory\appdata\local\programs\python\python38\lib\site-packages\mkdocstrings_handlers\python\templates\material\module.html", line 1, in top-level template code
    {% extends "_base/module.html" %}
  File "c:\users\cory\appdata\local\programs\python\python38\lib\site-packages\mkdocstrings_handlers\python\templates\material\_base\module.html", line 2, in top-level template code
    {% if config.show_if_no_docstring or module.has_docstrings %}
  File "c:\users\cory\appdata\local\programs\python\python38\lib\site-packages\jinja2\environment.py", line 474, in getattr
    return getattr(obj, attribute)
  File "c:\users\cory\appdata\local\programs\python\python38\lib\site-packages\griffe\dataclasses.py", line 353, in has_docstrings
    return self.has_docstring or any(member.has_docstrings for member in self.members.values())  # noqa: DAR201
  File "c:\users\cory\appdata\local\programs\python\python38\lib\site-packages\griffe\dataclasses.py", line 353, in <genexpr>
    return self.has_docstring or any(member.has_docstrings for member in self.members.values())  # noqa: DAR201
  File "c:\users\cory\appdata\local\programs\python\python38\lib\site-packages\griffe\dataclasses.py", line 759, in __getattr__
    attr = getattr(self.target, name)
  File "c:\users\cory\appdata\local\programs\python\python38\lib\site-packages\griffe\dataclasses.py", line 836, in target
    self.resolve_target()
  File "c:\users\cory\appdata\local\programs\python\python38\lib\site-packages\griffe\dataclasses.py", line 861, in resolve_target
    raise AliasResolutionError(self.target_path) from error
griffe.exceptions.AliasResolutionError: Could not resolve abc.abstractmethod

System (please complete the following information):

  • griffe version: 0.11.3
  • Python version: 3.8
  • OS: Windows 10

Infinite loop with some Google-style docstrings

Describe the bug
When running mkdocs build ... on a project I'm working on, it never terminates normally, and instead slowly consumes additional memory while showing no signs of progress being made.

I have not yet been able to determine what in the .pyx file is causing this bug to arise, but I will update this issue if/when I do.

Running a trace on the Mkdocs build reveals that Griffe gets stuck in a loop in google.py:

trace.log

To Reproduce

  1. Run mkdocs build ... on a project containing whatever sort of Google-style docstrings cause this issue.

Expected behavior
The docs should be built, and errors/warnings should be raised as appropriate.

System:

  • griffe version: 0.11.4 (from mkdocstrings[python]==0.18.0)
  • Python version: 3.10.2
  • OS: Linux

Support complex __all__ assignments

Is your feature request related to a problem? Please describe.
We claim to support __all__ variables for explicit exports. But we only do when it is assigned using a list/tuple and literal strings, not when summing lists and/or adding items later, and/or

Describe the solution you'd like
Support more complex assignments. Starred list elements and additions at least (+ and +=).

Describe alternatives you've considered
Stop reyling on __all__ and always resolve implicitly.

Additional context
Example: https://github.com/django/django/blob/main/django/db/models/__init__.py

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.