Coverage for /usr/lib/python3/dist-packages/matplotlib/_docstring.py: 90%

39 statements  

« prev     ^ index     » next       coverage.py v7.4.4, created at 2025-06-14 15:25 +0200

1import inspect 

2 

3from . import _api 

4 

5 

6class Substitution: 

7 """ 

8 A decorator that performs %-substitution on an object's docstring. 

9 

10 This decorator should be robust even if ``obj.__doc__`` is None (for 

11 example, if -OO was passed to the interpreter). 

12 

13 Usage: construct a docstring.Substitution with a sequence or dictionary 

14 suitable for performing substitution; then decorate a suitable function 

15 with the constructed object, e.g.:: 

16 

17 sub_author_name = Substitution(author='Jason') 

18 

19 @sub_author_name 

20 def some_function(x): 

21 "%(author)s wrote this function" 

22 

23 # note that some_function.__doc__ is now "Jason wrote this function" 

24 

25 One can also use positional arguments:: 

26 

27 sub_first_last_names = Substitution('Edgar Allen', 'Poe') 

28 

29 @sub_first_last_names 

30 def some_function(x): 

31 "%s %s wrote the Raven" 

32 """ 

33 def __init__(self, *args, **kwargs): 

34 if args and kwargs: 

35 raise TypeError("Only positional or keyword args are allowed") 

36 self.params = args or kwargs 

37 

38 def __call__(self, func): 

39 if func.__doc__: 

40 func.__doc__ = inspect.cleandoc(func.__doc__) % self.params 

41 return func 

42 

43 def update(self, *args, **kwargs): 

44 """ 

45 Update ``self.params`` (which must be a dict) with the supplied args. 

46 """ 

47 self.params.update(*args, **kwargs) 

48 

49 

50class _ArtistKwdocLoader(dict): 

51 def __missing__(self, key): 

52 if not key.endswith(":kwdoc"): 

53 raise KeyError(key) 

54 name = key[:-len(":kwdoc")] 

55 from matplotlib.artist import Artist, kwdoc 

56 try: 

57 cls, = [cls for cls in _api.recursive_subclasses(Artist) 

58 if cls.__name__ == name] 

59 except ValueError as e: 

60 raise KeyError(key) from e 

61 return self.setdefault(key, kwdoc(cls)) 

62 

63 

64class _ArtistPropertiesSubstitution(Substitution): 

65 """ 

66 A `.Substitution` with two additional features: 

67 

68 - Substitutions of the form ``%(classname:kwdoc)s`` (ending with the 

69 literal ":kwdoc" suffix) trigger lookup of an Artist subclass with the 

70 given *classname*, and are substituted with the `.kwdoc` of that class. 

71 - Decorating a class triggers substitution both on the class docstring and 

72 on the class' ``__init__`` docstring (which is a commonly required 

73 pattern for Artist subclasses). 

74 """ 

75 

76 def __init__(self): 

77 self.params = _ArtistKwdocLoader() 

78 

79 def __call__(self, obj): 

80 super().__call__(obj) 

81 if isinstance(obj, type) and obj.__init__ != object.__init__: 

82 self(obj.__init__) 

83 return obj 

84 

85 

86def copy(source): 

87 """Copy a docstring from another source function (if present).""" 

88 def do_copy(target): 

89 if source.__doc__: 

90 target.__doc__ = source.__doc__ 

91 return target 

92 return do_copy 

93 

94 

95# Create a decorator that will house the various docstring snippets reused 

96# throughout Matplotlib. 

97dedent_interpd = interpd = _ArtistPropertiesSubstitution()