|
15 | 15 |
|
16 | 16 | from __future__ import annotations
|
17 | 17 |
|
| 18 | +import ast |
18 | 19 | import re
|
19 |
| -from ast import literal_eval |
20 |
| -from typing import Callable, List, Optional, cast |
| 20 | +import sys |
| 21 | +from typing import Any, Callable, List, Optional, cast |
21 | 22 |
|
22 | 23 | from griffe import Docstring, Object
|
23 | 24 | from mkdocstrings import get_logger
|
@@ -353,7 +354,7 @@ def doc_value_offset_to_location(doc: Docstring, offset: int) -> tuple[int,int]:
|
353 | 354 | try:
|
354 | 355 | source = doc.source
|
355 | 356 | # compute docstring without cleaning up spaces and indentation
|
356 |
| - rawvalue = str(literal_eval(source)) |
| 357 | + rawvalue = str(safe_eval(source)) |
357 | 358 |
|
358 | 359 | # adjust line offset by number of lines removed from front of docstring
|
359 | 360 | lineoffset += leading_space(rawvalue).count("\n")
|
@@ -388,3 +389,13 @@ def leading_space(s: str) -> str:
|
388 | 389 | if m := re.match(r"\s*", s):
|
389 | 390 | return m[0]
|
390 | 391 | return "" # pragma: no cover
|
| 392 | + |
| 393 | +if sys.version_info < (3, 10) or True: |
| 394 | + # TODO: remove when 3.9 support is dropped |
| 395 | + # In 3.9, literal_eval cannot handle comments in input |
| 396 | + def safe_eval(s: str) -> Any: |
| 397 | + """Safely evaluate a string expression.""" |
| 398 | + return eval(s) #eval(s, dict(__builtins__={}), {}) |
| 399 | +else: |
| 400 | + save_eval = ast.literal_eval |
| 401 | + |
0 commit comments