From 15badca5680b666082f7f17bd946de461355e9cf Mon Sep 17 00:00:00 2001 From: Fabrice Normandin Date: Thu, 3 Aug 2023 10:55:22 -0400 Subject: [PATCH] Use cached versions of inspect.getdoc/getsource Fixes #278 Signed-off-by: Fabrice Normandin --- simple_parsing/decorators.py | 4 ++-- simple_parsing/docstring.py | 11 ++++++++--- simple_parsing/wrappers/dataclass_wrapper.py | 14 +++++++------- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/simple_parsing/decorators.py b/simple_parsing/decorators.py index c6235eef..68580eab 100644 --- a/simple_parsing/decorators.py +++ b/simple_parsing/decorators.py @@ -8,7 +8,7 @@ from typing import Any, Callable, NamedTuple import docstring_parser as dp - +from simple_parsing.docstring import dp_parse, inspect_getdoc from . import helpers, parsing @@ -55,7 +55,7 @@ def _wrapper(*other_args, **other_kwargs) -> Any: parameters = signature.parameters # Parse docstring to use as help strings - docstring = dp.parse(inspect.getdoc(function) or "") + docstring = dp_parse(inspect_getdoc(function) or "") docstring_param_description = { param.arg_name: param.description for param in docstring.params } diff --git a/simple_parsing/docstring.py b/simple_parsing/docstring.py index c7bc16e5..17d52d0a 100644 --- a/simple_parsing/docstring.py +++ b/simple_parsing/docstring.py @@ -5,12 +5,17 @@ import functools import inspect + +# from inspect import from dataclasses import dataclass from logging import getLogger import docstring_parser as dp from docstring_parser.common import Docstring +dp_parse = functools.lru_cache(2048)(dp.parse) +inspect_getsource = functools.lru_cache(2048)(inspect.getsource) +inspect_getdoc = functools.lru_cache(2048)(inspect.getdoc) logger = getLogger(__name__) @@ -102,7 +107,7 @@ def _get_attribute_docstring(dataclass: type, field_name: str) -> AttributeDocSt Doesn't inspect base classes. """ try: - source = inspect.getsource(dataclass) + source = inspect_getsource(dataclass) except (TypeError, OSError) as e: logger.debug( UserWarning( @@ -114,9 +119,9 @@ def _get_attribute_docstring(dataclass: type, field_name: str) -> AttributeDocSt # Parse docstring to use as help strings desc_from_cls_docstring = "" - cls_docstring = inspect.getdoc(dataclass) + cls_docstring = inspect_getdoc(dataclass) if cls_docstring: - docstring: Docstring = dp.parse(cls_docstring) + docstring: Docstring = dp_parse(cls_docstring) for param in docstring.params: if param.arg_name == field_name: desc_from_cls_docstring = param.description or "" diff --git a/simple_parsing/wrappers/dataclass_wrapper.py b/simple_parsing/wrappers/dataclass_wrapper.py index 2c00c98d..6a8c2bf4 100644 --- a/simple_parsing/wrappers/dataclass_wrapper.py +++ b/simple_parsing/wrappers/dataclass_wrapper.py @@ -10,13 +10,13 @@ from logging import getLogger from typing import Any, Callable, Generic, TypeVar, cast -import docstring_parser as dp from typing_extensions import Literal -from .. import docstring, utils -from ..utils import Dataclass, DataclassT, is_dataclass_instance, is_dataclass_type -from .field_wrapper import FieldWrapper -from .wrapper import Wrapper +from simple_parsing import docstring, utils +from simple_parsing.docstring import dp_parse, inspect_getdoc +from simple_parsing.utils import Dataclass, DataclassT, is_dataclass_instance, is_dataclass_type +from simple_parsing.wrappers.field_wrapper import FieldWrapper +from simple_parsing.wrappers.wrapper import Wrapper logger = getLogger(__name__) @@ -327,11 +327,11 @@ def description(self) -> str: # NOTE: The class docstring may be EXTRELEMY LARGE. - class_docstring = inspect.getdoc(self.dataclass) or "" + class_docstring = inspect_getdoc(self.dataclass) or "" if not class_docstring: return "" - doc = dp.parse(class_docstring) + doc = dp_parse(class_docstring) from simple_parsing.decorators import _description_from_docstring