Run `black` on python code blocks in documentation files

Overview

Build Status Azure DevOps coverage pre-commit.ci status

blacken-docs

Run black on python code blocks in documentation files.

install

pip install blacken-docs

usage

blacken-docs provides a single executable (blacken-docs) which will modify .rst / .md / .tex files in place.

It currently supports the following black options:

  • -l / --line-length
  • -t / --target-version
  • -S / --skip-string-normalization

Following additional parameters can be used:

  • -E / --skip-errors

blacken-docs will format code in the following block types:

(markdown)

    ```python
    def hello():
        print("hello world")
    ```

(rst)

    .. code-block:: python

        def hello():
            print("hello world")

(rst pycon)

    .. code-block:: pycon

        >>> def hello():
        ...     print("hello world")
        ...

(latex)

\begin{minted}{python}
def hello():
    print("hello world")
\end{minted}

(latex with pythontex)

\begin{pycode}
def hello():
    print("hello world")
\end{pycode}

(markdown/rst in python docstrings)

def f():
    """docstring here

    .. code-block:: python

        print("hello world")

    ```python
    print("hello world")
    ```
    """

usage with pre-commit

See pre-commit for instructions

Sample .pre-commit-config.yaml:

-   repo: https://github.com/asottile/blacken-docs
    rev: v1.9.2
    hooks:
    -   id: blacken-docs
        additional_dependencies: [black==...]

Since black is currently a moving target, it is suggested to pin black to a specific version using additional_dependencies.

Comments
  • Parse error for >>> prompt in code examples

    Parse error for >>> prompt in code examples

    Sphinx supports docs code examples with a prompt and output, as in the example from http://www.sphinx-doc.org/en/stable/markup/code.html

    >>> 1 + 1
    2
    

    Such code blocks are present in most docs files in the projects I work on, and blacken-docs gives a "code block parse error" for those and I think skips them completely, so doesn't work for me (and I think many other people / projects) at the moment.

    There must be some code in sphinx to parse those out, and to syntax highlight the rest of the code, so it should be possible to import and use that part of sphinx and only process the code after stripping the >>> out.

    enhancement help wanted 
    opened by cdeil 11
  • compatibility with jupyter-sphinx

    compatibility with jupyter-sphinx

    I would like to use this on rst files that are used in combination with https://github.com/jupyter/jupyter-sphinx.

    Here the code blocks are formatted like:

    .. jupyter-execute::
        :hide-code:
    
        code_here
    
    # or
    
    .. jupyter-execute::
    
        code_here
    

    Specifically, I would like to use it for the Adaptive documentation (repo).

    I've made an attempt myself, but I can't match @asottile's regex wizardry 😉

    enhancement good first issue 
    opened by basnijholt 9
  • Add option to format rST `::` literal code blocks

    Add option to format rST `::` literal code blocks

    I have a project that uses Sphinx and we have a fair number of literal code blocks in our docs. I would rather not have to ask contributors to not use literal code blocks.

    Would you be willing to add an option to format rST literal code blocks (or accept a PR adding such an option)?

    question 
    opened by auscompgeek 8
  • pass --check option to black

    pass --check option to black

    black supports --check option, useful for CI:

    --check                           Don't write the files back, just return the
                                      status.  Return code 0 means nothing would
                                      change.  Return code 1 means some files
                                      would be reformatted.  Return code 123 means
                                      there was an internal error.
    

    I've read the discussion in #3. It is helpful, but I believe there should be a way to use blacken-docs in CI without depending on pre-commit tool.

    Are you open to this feature?

    opened by shamrin 7
  • `blacken-docs` removes empty lines between methods.

    `blacken-docs` removes empty lines between methods.

    Hello,

    I hit an interesting behavior in markdown documents when formatting doctest examples in the pycon code blocks.

    Let say we have this python code in the usage.py file:

    class Robot:
    
        def __init__(self, servo, controller, settings):
            self.servo = servo
            self.controller = controller
            self.settings = settings
    
        def run(self):
            while True:
                events = self.accept_events()
                if not events:
                    break
                self.process(events)
    
        def accept_events(self):
            # We can inject methods.
            return self.controller()
    
        def process(self, events):
            # We can inject dictionaries.
            max_point = self.settings["max_point"]
            for event in events:
                if event.x > max_point:
                    # We can inject objects.
                    self.servo.reverse("x")
                if event.y > max_point:
                    self.servo.reverse("y")
    
    

    Then I apply black to this file it will produce this change:

    $ black usage.py
    
    diff --git a/usage.py b/usage.py
    index 1789079..b63d5ff 100644
    --- a/usage.py
    +++ b/usage.py
    @@ -1,5 +1,4 @@
     class Robot:
    -
         def __init__(self, servo, controller, settings):
             self.servo = servo
             self.controller = controller
    @@ -25,4 +24,3 @@ class Robot:
                     self.servo.reverse("x")
                 if event.y > max_point:
                     self.servo.reverse("y")
    -
    

    So, let's say we include the same code snippet in the markdown document usage.md:

    ```pycon
    
    >>> class Robot:
    ...
    ...     def __init__(self, servo, controller, settings):
    ...         self.servo = servo
    ...         self.controller = controller
    ...         self.settings = settings
    ...
    ...     def run(self):
    ...         while True:
    ...             events = self.accept_events()
    ...             if not events:
    ...                 break
    ...             self.process(events)
    ...
    ...     def accept_events(self):
    ...         # We can inject methods.
    ...         return self.controller()
    ...
    ...     def process(self, events):
    ...         # We can inject dictionaries.
    ...         max_point = self.settings["max_point"]
    ...         for event in events:
    ...             if event.x > max_point:
    ...                 # We can inject objects.
    ...                 self.servo.reverse("x")
    ...             if event.y > max_point:
    ...                 self.servo.reverse("y")
    ...
    
    ```
    

    When I apply blacken-docs to the markdown file it will remove empty lines between methods:

    $ blacken-docs usage.md
    
    diff --git a/usage.md b/usage.md
    index 7c38b1b..ba2566f 100644
    --- a/usage.md
    +++ b/usage.md
    @@ -1,23 +1,19 @@
     ```pycon
    
     >>> class Robot:
    -...
     ...     def __init__(self, servo, controller, settings):
     ...         self.servo = servo
     ...         self.controller = controller
     ...         self.settings = settings
    -...
     ...     def run(self):
     ...         while True:
     ...             events = self.accept_events()
     ...             if not events:
     ...                 break
     ...             self.process(events)
    -...
     ...     def accept_events(self):
     ...         # We can inject methods.
     ...         return self.controller()
    -...
     ...     def process(self, events):
     ...         # We can inject dictionaries.
     ...         max_point = self.settings["max_point"]
    

    This change does not seams right.

    You can use one of my projects if you need to test on real repository: https://github.com/proofit404/dependencies

    Thoughts?

    Best regards, Artem.

    opened by proofit404 5
  • Tool doesn't honor black preferences

    Tool doesn't honor black preferences

    I've adopted blacken-docs as a pre-commit hook on my projects, but today blacken-docs gave me trouble by performing string normalization where I prefer it not be:

    pip-run master $ git clone gh://jaraco/pip-run
    Cloning into 'pip-run'...
    remote: Enumerating objects: 466, done.
    remote: Counting objects: 100% (466/466), done.
    remote: Compressing objects: 100% (265/265), done.
    remote: Total 1785 (delta 278), reused 369 (delta 193), pack-reused 1319
    Receiving objects: 100% (1785/1785), 290.69 KiB | 4.21 MiB/s, done.
    Resolving deltas: 100% (1050/1050), done.
    pip-run master $ cd pip-run
    pip-run master $ git checkout d17b4e8
    Note: switching to 'd17b4e8'.
    
    You are in 'detached HEAD' state. You can look around, make experimental
    changes and commit them, and you can discard any commits you make in this
    state without impacting any branches by switching back to a branch.
    
    If you want to create a new branch to retain commits you create, you may
    do so (now or later) by using -c with the switch command. Example:
    
      git switch -c <new-branch-name>
    
    Or undo this operation with:
    
      git switch -
    
    Turn off this advice by setting config variable advice.detachedHead to false
    
    HEAD is now at d17b4e8 Improve syntax in readme
    pip-run HEAD $ pre-commit install
    pre-commit installed at .git/hooks/pre-commit
    pip-run HEAD $ pre-commit run
    black................................................(no files to check)Skipped
    blacken-docs.........................................(no files to check)Skipped
    pip-run HEAD $ pre-commit run --all
    black....................................................................Passed
    blacken-docs.............................................................Failed
    - hook id: blacken-docs
    - exit code: 1
    - files were modified by this hook
    
    README.rst: Rewriting...
    
    pip-run HEAD $ git diff
    diff --git a/README.rst b/README.rst
    index 87c34d9..6fa9b2e 100644
    --- a/README.rst
    +++ b/README.rst
    @@ -177,11 +177,11 @@ First, add a ``__requires__`` directive at the head of the script:
     
         #!/usr/bin/env python
     
    -    __requires__ = ['requests']
    +    __requires__ = ["requests"]
     
         import requests
     
    -    req = requests.get('https://pypi.org/project/pip-run')
    +    req = requests.get("https://pypi.org/project/pip-run")
         print(req.status_code)
     
     Then, simply invoke that script with pip-run::
    @@ -199,10 +199,11 @@ allowing a script to specify a custom package index:
     
         #!/usr/bin/env python
     
    -    __requires__ = ['my_private_package']
    -    __index_url__ = 'https://my.private.index/'
    +    __requires__ = ["my_private_package"]
    +    __index_url__ = "https://my.private.index/"
     
         import my_private_package
    +
         ...
     
     Supplying parameters to Pip
    
    pip-run HEAD $ head -n 6 pyproject.toml | tail -n 2
    [tool.black]
    skip-string-normalization = true
    

    Is it by design that the configuration for black is different than that for blacken-docs? Is there a way that blacken-docs could be configured to honor the black config?

    enhancement 
    opened by jaraco 5
  • Support Markdown include syntax ({! myfile.py !})

    Support Markdown include syntax ({! myfile.py !})

    The "include" syntax should be skipped instead of bailing out:

    docs/howtos/authenticate-web-ui-users.md:71: code block parse error Cannot parse: 1:1: {! docs/howtos/aiohttp-oauth-redirect-example.py !}
    

    Background: we "include" longer Python files (which are separately formatted with black) in Markdown with the mdx_include markdown extension.

    My proposal would be to detect code blocks which just contain such include syntax ({! ... !}) and ignore them.

    opened by hjacobs 5
  • --diff option

    --diff option

    We have black checks in our CI to verify that any PRs/pushes are compliant. It would be nice to be able to include blacken-docs in these checks, but I don't want the CI steps to modify any code. Having a --diff option similar to black would be a nice feature that would show in our CI what needs to change.

    enhancement question 
    opened by mattsb42-aws 5
  • async/await keywords not recognized in code block?

    async/await keywords not recognized in code block?

    Hi,

    My documentation looks like this:

    .. code-block:: python
    
        async with aiohttp.ClientSession() as session:
            gh = GitHubAPI(session, "mariatta", oauth_token=os.getenv("GH_AUTH"))
    

    When I run blacken-docs, I'm getting this error:

    code block parse error Cannot parse: 1:6: async with aiohttp.ClientSession() as session:
    

    But when I removed the async keyword, it works:

    .. code-block:: python
    
        with aiohttp.ClientSession() as session:
            gh = GitHubAPI(session, "mariatta", oauth_token=os.getenv("GH_AUTH"))
    

    Same problem when I have this type of code block:

    .. code-block:: python
    
        await gh.patch(url, data={"state": "closed"})
    

    Removing the await keyword works. Any idea?

    Thanks.

    opened by Mariatta 5
  • line number error with code-block:: python

    line number error with code-block:: python

    I don't understand this one, with python code-block I get a line number error (using pre-commit) but if I remove the language the error goes away but I get no syntax highlighting? Example is here: https://github.com/sarnold/python-daemonizer

    This generates an error:

    .. code-block:: python
    
      from daemon import Daemon
    
      class pantalaimon(Daemon):
          def run(self):
              # Do stuff
    

    but the same thing without the language does not:

    .. code-block::
    
      from daemon import Daemon
    
      class pantalaimon(Daemon):
          def run(self):
              # Do stuff
    

    The latter one highlights in sphinx docs but not on Github :(

    opened by sarnold 4
  • pweave mode added

    pweave mode added

    I find the literate programming program Pweave (http://mpastell.com/pweave/examples/index.html) very handy. Nicer yet is to have the python code in a pweave file beautified. I tested the PR on the pweave file http://mpastell.com/pweave/_downloads/FIR_design_verb.texw, and it runs perfectly.

    Black runs automatically in my emacs when I save a file. I don't know whether you like the small changes black made in blacken-docs.py. If you don't, I'll make another pull request

    opened by ndvanforeest 4
  • "--dry-run" flag

    Let's say I need to "blacken docs" for a large project, case in point https://github.com/django/django/pull/16261

    It would be useful to separate commits into two:

    1. The manual changes, to current docs, required for blacken-docs command to work without errors.
    2. The automated changes by running blacken-docs.

    I.e. Part of what @carltongibson suggested here https://github.com/django/django/pull/16261#issuecomment-1333341758

    So this issue is about allowing the user to add a -D or --dry-run flag to the current command. This would prevent the command from changing files.

    opened by jvzammit 0
  • Added regex for Sphinx default language blocks.

    Added regex for Sphinx default language blocks.

    This is initial sketch to fix #195. It adds processing for Sphinx' default language blocks, marked with paragraphs ending ::, which is common to all Sphinx projects using the defaults there (i.e. sphinx-quickstart generated).

    • [ ] No doubt there's a wiggle or two in the regex, that we'll no doubt find running it against Django's docs.
    • [x] Would need a CLI flag. https://github.com/adamchainz/blacken-docs/pull/196/commits/a121cc09e0d0a26670ebef0b8ccdd1495307f7a6
    • [ ] ... (what else) ...

    Opening early for input, and to let us experiment on the Django docs.

    opened by carltongibson 0
  • RST: Detect `::` signifying default language code-block.

    RST: Detect `::` signifying default language code-block.

    blacken-docs will do this:

    - call ``reset_queries()``, like this::
    + call ``reset_queries()``, like this:
    + 
    +  .. code-block:: python
    

    But it's an old-as-time RST convention that the :: means the following code block is the default language (i.e. Python)

    Not respecting that is quite a lot of noise. Is there a way to control it? Could there be?

    Thanks!

    Refs https://github.com/django/django/pull/16261

    opened by carltongibson 12
  • Add possibilities to skip blocks and lines?

    Add possibilities to skip blocks and lines?

    Background:

    When we implemented blacken-docs in Read the Docs, we had a couple of cases where we would have liked to skip linting of the code example. But we also didn't want to put # noqa in the code-examples themselves, since that means copy-pasting the code would also require additional clean-up. Our cases were - however - easy to ignore and move on from. So we did.

    Now, I see a Django proposal to use blacken-docs is generating mostly great changes, but there are also a few issues getting the PR merged.

    Solution?

    I'm not sure what would be a good way forwards. But I get the idea that being able to specify what to skip might work well.

    Please have a look here: https://github.com/django/django/pull/16261

    Thanks for the great project :heart:

    opened by benjaoming 0
  • Support black's --experimental-string-processing flag

    Support black's --experimental-string-processing flag

    It would be great if blacken-docs would also allow using the --experimental-string-processing to split lines in the docstring if they reach the line length limit.

    opened by feluelle 0
Owner
Anthony Sottile
@pre-commit @pytest-dev @tox-dev
Anthony Sottile
Documentation of the QR code found on new Austrian ID cards.

Austrian ID Card QR Code This document aims to be a complete documentation of the format used in the QR area on the back of new Austrian ID cards (Per

Gabriel Huber 9 Dec 12, 2022
Automatic links from code examples to reference documentation

sphinx-codeautolink Automatic links from Python code examples to reference documentation at the flick of a switch! sphinx-codeautolink analyses the co

Felix Hildén 41 Dec 17, 2022
A curated list of awesome tools for Sphinx Python Documentation Generator

Awesome Sphinx (Python Documentation Generator) A curated list of awesome extra libraries, software and resources for Sphinx (Python Documentation Gen

Hyunjun Kim 831 Dec 27, 2022
API Documentation for Python Projects

API Documentation for Python Projects. Example pdoc -o ./html pdoc generates this website: pdoc.dev/docs. Installation pip install pdoc pdoc is compat

mitmproxy 1.4k Jan 7, 2023
📖 Generate markdown API documentation from Google-style Python docstring. The lazy alternative to Sphinx.

lazydocs Generate markdown API documentation for Google-style Python docstring. Getting Started • Features • Documentation • Support • Contribution •

Machine Learning Tooling 118 Dec 31, 2022
Main repository for the Sphinx documentation builder

Sphinx Sphinx is a tool that makes it easy to create intelligent and beautiful documentation for Python projects (or other documents consisting of mul

null 5.1k Jan 2, 2023
Literate-style documentation generator.

888888b. 888 Y88b 888 888 888 d88P 888 888 .d8888b .d8888b .d88b. 8888888P" 888 888 d88P" d88P" d88""88b 888 888 888

Pycco 808 Dec 27, 2022
Main repository for the Sphinx documentation builder

Sphinx Sphinx is a tool that makes it easy to create intelligent and beautiful documentation for Python projects (or other documents consisting of mul

null 5.1k Jan 4, 2023
Project documentation with Markdown.

MkDocs Project documentation with Markdown. View the MkDocs documentation. Project release notes. Visit the MkDocs wiki for community resources, inclu

MkDocs 15.6k Jan 2, 2023
Watch a Sphinx directory and rebuild the documentation when a change is detected. Also includes a livereload enabled web server.

sphinx-autobuild Rebuild Sphinx documentation on changes, with live-reload in the browser. Installation sphinx-autobuild is available on PyPI. It can

Executable Books 440 Jan 6, 2023
Your Project with Great Documentation.

Read Latest Documentation - Browse GitHub Code Repository The only thing worse than documentation never written, is documentation written but never di

Timothy Edmund Crosley 809 Dec 28, 2022
:blue_book: Automatic documentation from sources, for MkDocs.

mkdocstrings Automatic documentation from sources, for MkDocs. Features Python handler features Requirements Installation Quick usage Features Languag

Timothée Mazzucotelli 1.1k Dec 31, 2022
:blue_book: Automatic documentation from sources, for MkDocs.

mkdocstrings Automatic documentation from sources, for MkDocs. Features - Python handler - Requirements - Installation - Quick usage Features Language

null 1.1k Jan 4, 2023
Seamlessly integrate pydantic models in your Sphinx documentation.

Seamlessly integrate pydantic models in your Sphinx documentation.

Franz Wöllert 71 Dec 26, 2022
Documentation generator for C++ based on Doxygen and mosra/m.css.

mosra/m.css is a Doxygen-based documentation generator that significantly improves on Doxygen's default output by controlling some of Doxygen's more unruly options, supplying it's own slick HTML+CSS generation and adding a fantastic live search feature.

Mark Gillard 109 Dec 7, 2022
NetBox plugin for BGP related objects documentation

Netbox BGP Plugin Netbox plugin for BGP related objects documentation. Compatibility This plugin in compatible with NetBox 2.10 and later. Installatio

Nikolay Yuzefovich 133 Dec 27, 2022
Automated Integration Testing and Live Documentation for your API

Automated Integration Testing and Live Documentation for your API

ScanAPI 1.3k Dec 30, 2022
Swagger Documentation Generator for Django REST Framework: deprecated

Django REST Swagger: deprecated (2019-06-04) This project is no longer being maintained. Please consider drf-yasg as an alternative/successor. I haven

Marc Gibbons 2.6k Jan 3, 2023
Test utility for validating OpenAPI documentation

DRF OpenAPI Tester This is a test utility to validate DRF Test Responses against OpenAPI 2 and 3 schema. It has built-in support for: OpenAPI 2/3 yaml

snok 106 Jan 5, 2023