|
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