|
| 1 | +from matplotlib import cbook |
| 2 | + |
| 3 | +class Substitution(object): |
| 4 | + """ |
| 5 | + A decorator to take a function's docstring and perform string |
| 6 | + substitution on it. |
| 7 | + |
| 8 | + This decorator should be robust even if func.__doc__ is None |
| 9 | + (for example, if -OO was passed to the interpreter) |
| 10 | + |
| 11 | + Usage: construct a docstring.Substitution with a sequence or |
| 12 | + dictionary suitable for performing substitution; then |
| 13 | + decorate a suitable function with the constructed object. e.g. |
| 14 | + |
| 15 | + sub_author_name = Substitution(author='Jason') |
| 16 | + |
| 17 | + @sub_author_name |
| 18 | + def some_function(x): |
| 19 | + "%(author)s wrote this function" |
| 20 | + |
| 21 | + # note that some_function.__doc__ is now "Jason wrote this function" |
| 22 | + |
| 23 | + One can also use positional arguments. |
| 24 | + |
| 25 | + sub_first_last_names = Substitution('Edgar Allen', 'Poe') |
| 26 | + |
| 27 | + @sub_first_last_names |
| 28 | + def some_function(x): |
| 29 | + "%s %s wrote the Raven" |
| 30 | + """ |
| 31 | + def __init__(self, *args, **kwargs): |
| 32 | + assert not (args and kwargs), "Only positional or keyword args are allowed" |
| 33 | + self.params = args or kwargs |
| 34 | + |
| 35 | + def __call__(self, func): |
| 36 | + func.__doc__ = func.__doc__ and func.__doc__ % self.params |
| 37 | + return func |
| 38 | + |
| 39 | + def update(self, *args, **kwargs): |
| 40 | + "Assume self.params is a dict and update it with supplied args" |
| 41 | + self.params.update(*args, **kwargs) |
| 42 | + |
| 43 | + @classmethod |
| 44 | + def from_params(cls, params): |
| 45 | + """ |
| 46 | + In the case where the params is a mutable sequence (list or dictionary) |
| 47 | + and it may change before this class is called, one may explicitly use |
| 48 | + a reference to the params rather than using *args or **kwargs which will |
| 49 | + copy the values and not reference them. |
| 50 | + """ |
| 51 | + result = cls() |
| 52 | + result.params = params |
| 53 | + return result |
| 54 | + |
| 55 | +class Appender(object): |
| 56 | + """ |
| 57 | + A function decorator that will append an addendum to the docstring |
| 58 | + of the target function. |
| 59 | + |
| 60 | + This decorator should be robust even if func.__doc__ is None |
| 61 | + (for example, if -OO was passed to the interpreter). |
| 62 | + |
| 63 | + Usage: construct a docstring.Appender with a string to be joined to |
| 64 | + the original docstring. An optional 'join' parameter may be supplied |
| 65 | + which will be used to join the docstring and addendum. e.g. |
| 66 | + |
| 67 | + add_copyright = Appender("Copyright (c) 2009", join='\n') |
| 68 | + |
| 69 | + @add_copyright |
| 70 | + def my_dog(has='fleas'): |
| 71 | + "This docstring will have a copyright below" |
| 72 | + pass |
| 73 | + """ |
| 74 | + def __init__(self, addendum, join=''): |
| 75 | + self.addendum = addendum |
| 76 | + self.join = join |
| 77 | + |
| 78 | + def __call__(self, func): |
| 79 | + docitems = [func.__doc__, self.addendum] |
| 80 | + func.__doc__ = func.__doc__ and ''.join(docitems) |
| 81 | + return func |
| 82 | + |
| 83 | +def dedent(func): |
| 84 | + "Dedent a docstring (if present)" |
| 85 | + func.__doc__ = func.__doc__ and cbook.dedent(func.__doc__) |
| 86 | + return func |
| 87 | + |
| 88 | +def copy(source): |
| 89 | + "Copy a docstring from another source function (if present)" |
| 90 | + def do_copy(target): |
| 91 | + if source.__doc__: |
| 92 | + target.__doc__ = source.__doc__ |
| 93 | + return target |
| 94 | + return do_copy |
| 95 | + |
| 96 | +# create a decorator that will house the various documentation that |
| 97 | +# is reused throughout matplotlib |
| 98 | +interpd = Substitution() |
| 99 | + |
| 100 | +def dedent_interpd(func): |
| 101 | + """A special case of the interpd that first performs a dedent on |
| 102 | + the incoming docstring""" |
| 103 | + return interpd(dedent(func)) |
| 104 | + |
| 105 | +def copy_dedent(source): |
| 106 | + """A decorator that will copy the docstring from the source and |
| 107 | + then dedent it""" |
| 108 | + # note the following is ugly because "Python is not a functional |
| 109 | + # language" - GVR. Perhaps one day, functools.compose will exist. |
| 110 | + # or perhaps not. |
| 111 | + # http://mail.python.org/pipermail/patches/2007-February/021687.html |
| 112 | + return lambda target: dedent(copy(source)(target)) |
0 commit comments