Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add possibilities to skip blocks and lines? #193

Open
benjaoming opened this issue Nov 8, 2022 · 3 comments · May be fixed by #287
Open

Add possibilities to skip blocks and lines? #193

benjaoming opened this issue Nov 8, 2022 · 3 comments · May be fixed by #287

Comments

@benjaoming
Copy link
Contributor

benjaoming commented Nov 8, 2022

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: django/django#16261

Thanks for the great project ❤️

@pawamoy
Copy link

pawamoy commented Jul 13, 2023

I'm using the pymdownx.snippets Markdown extension to include some Python code into a Python code block:

```python
--8<-- "docs/snippets/script.py
```

...and blacken-docs reformats it to:

```python
--8 < -- "docs/snippets/script.py
```

...breaking the extension's syntax.

As a workaround, I'm using Markdown Exec (very hacky):

```python exec="1" result="python"
print('--8<-- "docs/examples/model_ext.py"')
```

This code blocks gets executed, so prints the actual snippet line, and this line then gets re-rendered as Markdown, wrapping the result into a python code block. As I said, very hacky 🤣

Instead, it would be nice if I could somehow tell blacken-docs to ignore this code block, preferably without comments inside the code.

@adamchainz
Copy link
Owner

adamchainz commented Aug 16, 2023

Adding skip syntax would be great. It needs to be added for all supported markup languages. I think the easiest is to support on/off comments, and then we can ignore any detected examples that overlap the disabled regions. For example, in Markdown:

<!-- blacken-docs:off -->
```python
--8<-- "docs/snippets/script.py
```
<!-- blacken-docs:on -->

This would be quite a large undertaking, so I'm personally not going to invest in it right now. But I would love to see a PR.

@pawamoy
Copy link

pawamoy commented Sep 16, 2023

What do you think of this:

  • in format_str, we find all occurrences of the on/off comments with a regex, and store their positions
  • we use these positions to compute ranges of position in the file that should not be formatted
  • we define a function with a closure on these ranges that accepts a range and tells if it should be ignored (see snippet below)
  • each function used in re.sub (_md_match, etc.) adds a condition like this: if _off_range(match.start(), match.end()): return code_unchanged

Quick example:

comments = find_all_comments()
off_ranges = []
off_start = None
for comment in comments:
    if "off" in comment and off_start is None:
        off_start = comment.start()
    elif "on" in comment and off_start is not None:
        off_ranges.append((off_start, comment.end()))
        off_start = None


def _off_range(start, end):
    for range in off_ranges:  # closure
        if start >= range[0] and end <= range[1]:
            return True
    return False
    # could rewrite as `return any(comprehension)`
    # could use a partial instead of a closure


def _md_match(match):
    if _off_range(match.start(), match.end()):
        return match.group(0)
    ...  # otherwise process normally

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants