|
6 | 6 | import re
|
7 | 7 | import sys
|
8 | 8 | from collections import ChainMap
|
| 9 | +from functools import lru_cache |
9 | 10 | from typing import Any, Sequence
|
10 | 11 |
|
11 | 12 | from griffe.dataclasses import Alias, Object
|
|
14 | 15 |
|
15 | 16 | from mkdocstrings.extension import PluginError
|
16 | 17 | from mkdocstrings.handlers.base import BaseRenderer, CollectorItem
|
| 18 | +from mkdocstrings.loggers import get_logger |
17 | 19 |
|
| 20 | +logger = get_logger(__name__) |
18 | 21 | # TODO: CSS classes everywhere in templates
|
19 | 22 | # TODO: name normalization (filenames, Jinja2 variables, HTML tags, CSS classes)
|
20 | 23 | # TODO: Jinja2 blocks everywhere in templates
|
@@ -145,15 +148,11 @@ def do_format_signature(self, signature: str, line_length: int) -> str:
|
145 | 148 | Returns:
|
146 | 149 | The same code, formatted.
|
147 | 150 | """
|
148 |
| - from black import Mode, format_str |
149 |
| - |
150 | 151 | code = signature.strip()
|
151 | 152 | if len(code) < line_length:
|
152 | 153 | return code
|
153 |
| - mode = Mode(line_length=line_length) |
154 |
| - formatted = format_str(f"def {code}: pass", mode=mode) |
155 |
| - # remove starting `def ` and trailing `: pass` |
156 |
| - return formatted[4:-5].strip()[:-1] |
| 154 | + formatter = _get_black_formatter() |
| 155 | + return formatter(code, line_length) |
157 | 156 |
|
158 | 157 | def do_order_members(self, members: Sequence[Object | Alias], order: Order) -> Sequence[Object | Alias]:
|
159 | 158 | """Order members given an ordering method.
|
@@ -209,3 +208,20 @@ def repl(match): # noqa: WPS430
|
209 | 208 | if code:
|
210 | 209 | text = f"<code>{text}</code>"
|
211 | 210 | return Markup(text).format(**variables)
|
| 211 | + |
| 212 | + |
| 213 | +@lru_cache(maxsize=1) |
| 214 | +def _get_black_formatter(): |
| 215 | + try: |
| 216 | + from black import Mode, format_str |
| 217 | + except ModuleNotFoundError: |
| 218 | + logger.warning("Formatting signatures requires Black to be installed.") |
| 219 | + return lambda text, _: text |
| 220 | + |
| 221 | + def formatter(code, line_length): # noqa: WPS430 |
| 222 | + mode = Mode(line_length=line_length) |
| 223 | + formatted = format_str(f"def {code}: pass", mode=mode) |
| 224 | + # remove starting `def ` and trailing `: pass` |
| 225 | + return formatted[4:-5].strip()[:-1] |
| 226 | + |
| 227 | + return formatter |
0 commit comments