1"""Decorators that don't go anywhere else.
2
3This module contains misc. decorators that don't really go with another module
4in :mod:`IPython.utils`. Before putting something here please see if it should
5go into another topical module in :mod:`IPython.utils`.
6"""
7
8#-----------------------------------------------------------------------------
9# Copyright (C) 2008-2011 The IPython Development Team
10#
11# Distributed under the terms of the BSD License. The full license is in
12# the file COPYING, distributed as part of this software.
13#-----------------------------------------------------------------------------
14
15#-----------------------------------------------------------------------------
16# Imports
17#-----------------------------------------------------------------------------
18from __future__ import annotations
19
20from collections.abc import Callable, Sequence
21from typing import Any, TypeVar
22
23from IPython.utils.docs import GENERATING_DOCUMENTATION
24
25F = TypeVar("F", bound=Callable[..., Any])
26
27#-----------------------------------------------------------------------------
28# Code
29#-----------------------------------------------------------------------------
30
31def flag_calls(func: Callable[..., Any]) -> Callable[..., Any]:
32 """Wrap a function to detect and flag when it gets called.
33
34 This is a decorator which takes a function and wraps it in a function with
35 a 'called' attribute. wrapper.called is initialized to False.
36
37 The wrapper.called attribute is set to False right before each call to the
38 wrapped function, so if the call fails it remains False. After the call
39 completes, wrapper.called is set to True and the output is returned.
40
41 Testing for truth in wrapper.called allows you to determine if a call to
42 func() was attempted and succeeded."""
43
44 # don't wrap twice
45 if hasattr(func, 'called'):
46 return func
47
48 def wrapper(*args: Any, **kw: Any) -> Any:
49 wrapper.called = False # type: ignore[attr-defined]
50 out = func(*args, **kw)
51 wrapper.called = True # type: ignore[attr-defined]
52 return out
53
54 wrapper.called = False # type: ignore[attr-defined]
55 wrapper.__doc__ = func.__doc__
56 return wrapper
57
58
59def undoc(func: F) -> F:
60 """Mark a function or class as undocumented.
61
62 This is found by inspecting the AST, so for now it must be used directly
63 as @undoc, not as e.g. @decorators.undoc
64 """
65 return func
66
67
68def sphinx_options(
69 show_inheritance: bool = True,
70 show_inherited_members: bool = False,
71 exclude_inherited_from: Sequence[str] = tuple(),
72) -> Callable[[F], F]:
73 """Set sphinx options"""
74
75 def wrapper(func: F) -> F:
76 if not GENERATING_DOCUMENTATION:
77 return func
78
79 func._sphinx_options = dict( # type: ignore[attr-defined]
80 show_inheritance=show_inheritance,
81 show_inherited_members=show_inherited_members,
82 exclude_inherited_from=exclude_inherited_from,
83 )
84 return func
85
86 return wrapper