kwdoc processing with decorators

Those of you with an interest in mpl docstring processing may want to
comment on this tracker item

https://sourceforge.net/tracker/index.php?func=detail&aid=2835685&group_id=80706&atid=560720

JDH

This patch has come a long way since initial submission, and I am
personally +1 on it, but it is wide reaching in the code and I'd like
to get a signoff at least from Eric who has done the most with the
docstrings before committing. Comments from anyone else are also
welcome of course. Darren, I think his latest approach satisfies your
requests, but I made the comment I would prefer some of the very
common combinations rolled up into single line decorators.

···

On Wed, Aug 12, 2009 at 7:12 AM, John Hunter<jdh2358@...149...> wrote:

Those of you with an interest in mpl docstring processing may want to
comment on this tracker item

https://sourceforge.net/tracker/index.php?func=detail&aid=2835685&group_id=80706&atid=560720

I appreciate how much time has gone into the patch, but this impacts
so much code I think it is important to really nail the
implementation. I think everything should be rolled up into a single
high level decorator if possible. I offered a suggestion in the
tracker. Consider:

with_doc(*args, **kwargs):
    mod_doc(f):
        if args:
            if not isinstance(args[0], str):
                # inherit docstring from first argument
                inherit = args.pop(0).__doc__
                if f.__doc__ is None:
                    f.__doc__ = inherit
                else:
                    f.__doc__ = inherit + '\n\n' + f.__doc__
        if kwargs:
            # mapping interpolation
            f.__doc__ = f.__doc__ % kwargs
        if args:
            try:
                # inserting
                f.__doc__ = f.__doc__ % args
            except TypeError:
                 # appending
                 if f.__doc__ is None:
                     f.__doc__ = ''
                 f.__doc__ = f.__doc__ + '\n\n'+ '\n\n'.join(args)
        return f
    return mod_doc

I left out the dedentation for now, and it is untested. This can cover
lots of ground, I think it can be chained on itself:

@with_doc('append me', prepend='prepend me as well')
@with_doc(other_method)
@with_doc('prepend me %(prepend)s')

If it is not possible, or possible but messy because of dedentation or
other reasons, to pack everything into a single high-level decorator,
then maybe there should be a few like:

inherit_doc(fun) overwrite or prepend with fun's docstring
insert_doc(*args, **kwargs) interpolate
append_doc(*args)

but since these are high-level decorators, chaining decorators would
result in repeated calls to dedent.

Darren

···

On Thu, Aug 13, 2009 at 7:44 AM, John Hunter<jdh2358@...149...> wrote:

On Wed, Aug 12, 2009 at 7:12 AM, John Hunter<jdh2358@...149...> wrote:

Those of you with an interest in mpl docstring processing may want to
comment on this tracker item

https://sourceforge.net/tracker/index.php?func=detail&aid=2835685&group_id=80706&atid=560720

This patch has come a long way since initial submission, and I am
personally +1 on it, but it is wide reaching in the code and I'd like
to get a signoff at least from Eric who has done the most with the
docstrings before committing. Comments from anyone else are also
welcome of course. Darren, I think his latest approach satisfies your
requests, but I made the comment I would prefer some of the very
common combinations rolled up into single line decorators.

I have not followed the conversation, so please forgive me if I am
talking bull**, but why are you not using functools.wraps? I have found
it is useful to make really sure that you are keeping all the
properties of a function that you want to decorate.

Gaël

PS: Some of the mayavi codebase should be changed to use wraps, so don't
take this as a blame, but more as a question :).

···

On Thu, Aug 13, 2009 at 10:12:23AM -0400, Darren Dale wrote:

I appreciate how much time has gone into the patch, but this impacts
so much code I think it is important to really nail the
implementation. I think everything should be rolled up into a single
high level decorator if possible. I offered a suggestion in the
tracker. Consider:

with_doc(*args, **kwargs):
    mod_doc(f):
        if args:
            if not isinstance(args[0], str):
                # inherit docstring from first argument
                inherit = args.pop(0).__doc__
                if f.__doc__ is None:
                    f.__doc__ = inherit
                else:
                    f.__doc__ = inherit + '\n\n' + f.__doc__
        if kwargs:
            # mapping interpolation
            f.__doc__ = f.__doc__ % kwargs
        if args:
            try:
                # inserting
                f.__doc__ = f.__doc__ % args
            except TypeError:
                 # appending
                 if f.__doc__ is None:
                     f.__doc__ = ''
                 f.__doc__ = f.__doc__ + '\n\n'+ '\n\n'.join(args)
        return f
    return mod_doc

Hi Gael,

···

On Thu, Aug 13, 2009 at 10:24 AM, Gael Varoquaux<gael.varoquaux@...427...> wrote:

On Thu, Aug 13, 2009 at 10:12:23AM -0400, Darren Dale wrote:

I appreciate how much time has gone into the patch, but this impacts
so much code I think it is important to really nail the
implementation. I think everything should be rolled up into a single
high level decorator if possible. I offered a suggestion in the
tracker. Consider:

with_doc(*args, **kwargs):
mod_doc(f):
if args:
if not isinstance(args[0], str):
# inherit docstring from first argument
inherit = args.pop(0).__doc__
if f.__doc__ is None:
f.__doc__ = inherit
else:
f.__doc__ = inherit + '\n\n' + f.__doc__
if kwargs:
# mapping interpolation
f.__doc__ = f.__doc__ % kwargs
if args:
try:
# inserting
f.__doc__ = f.__doc__ % args
except TypeError:
# appending
if f.__doc__ is None:
f.__doc__ = ''
f.__doc__ = f.__doc__ + '\n\n'+ '\n\n'.join(args)
return f
return mod_doc

I have not followed the conversation, so please forgive me if I am
talking bull**, but why are you not using functools.wraps? I have found
it is useful to make really sure that you are keeping all the
properties of a function that you want to decorate.

I am aware of functools.wraps and have used it myself. So far we are
only modifying and returning the original function, not a wrapped
version of the original, so functools.wraps is not necessary.

Darren

OK, as I suspected, I was not reading the code properly.

Thanks for your answer.

Gaël

···

On Thu, Aug 13, 2009 at 10:52:24AM -0400, Darren Dale wrote:

I am aware of functools.wraps and have used it myself. So far we are
only modifying and returning the original function, not a wrapped
version of the original, so functools.wraps is not necessary.

I don't think Jason is on the dev list, so I am CC-ing him. Please
make sure he is CC-d on all other conversations in this thread.

I appreciate how much time has gone into the patch, but this impacts
so much code I think it is important to really nail the
implementation. I think everything should be rolled up into a single
high level decorator if possible. I offered a suggestion in the
tracker. Consider:

with_doc(*args, **kwargs):
mod_doc(f):
if args:
if not isinstance(args[0], str):
# inherit docstring from first argument
inherit = args.pop(0).__doc__
if f.__doc__ is None:
f.__doc__ = inherit
else:
f.__doc__ = inherit + '\n\n' + f.__doc__
if kwargs:
# mapping interpolation
f.__doc__ = f.__doc__ % kwargs
if args:
try:
# inserting
f.__doc__ = f.__doc__ % args
except TypeError:
# appending
if f.__doc__ is None:
f.__doc__ = ''
f.__doc__ = f.__doc__ + '\n\n'+ '\n\n'.join(args)
return f
return mod_doc

I left out the dedentation for now, and it is untested. This can cover
lots of ground, I think it can be chained on itself:

@with_doc('append me', prepend='prepend me as well')
@with_doc(other_method)
@with_doc('prepend me %(prepend)s')

If it is not possible, or possible but messy because of dedentation or
other reasons, to pack everything into a single high-level decorator,
then maybe there should be a few like:

inherit_doc(fun) overwrite or prepend with fun's docstring
insert_doc(*args, **kwargs) interpolate
append_doc(*args)

but since these are high-level decorators, chaining decorators would
result in repeated calls to dedent.

Another thing to consider while cleaning this up is to not just put
the artist props into the kwdocd, but *anything* that needs
interpolating. So we could have one docstring.interpd into which all
keys 'Line2D', 'Patch', 'AvailableArrowstyles', 'PSD', 'scale_docs',
etc... Right now we have a hodge-podge of doc interpolation strings,
and it might make sense to simplify this by putting them all into a
single interp dict that can be used anywhere in mpl.

Jason, I hope we don't exhaust you with these suggestions -- this will
be a very nice cleanup and a big help for people using mpl in
installers like py2exe which strip out docs with the optimization
flags. But as Darren said we need to get this right and keep the
interface as simple as possible while preserving all the current
functionality. Thanks for all your efforts.

JDH

···

On Thu, Aug 13, 2009 at 9:12 AM, Darren Dale<dsdale24@...149...> wrote:

It suggest hashing out the basic approach and interface on the list
before applying it throughout the library.

Darren

···

On Thu, Aug 13, 2009 at 11:46 AM, John Hunter<jdh2358@...149...> wrote:

On Thu, Aug 13, 2009 at 9:12 AM, Darren Dale<dsdale24@...149...> wrote:

I don't think Jason is on the dev list, so I am CC-ing him. Please
make sure he is CC-d on all other conversations in this thread.

I appreciate how much time has gone into the patch, but this impacts
so much code I think it is important to really nail the
implementation. I think everything should be rolled up into a single
high level decorator if possible. I offered a suggestion in the
tracker. Consider:

with_doc(*args, **kwargs):
mod_doc(f):
if args:
if not isinstance(args[0], str):
# inherit docstring from first argument
inherit = args.pop(0).__doc__
if f.__doc__ is None:
f.__doc__ = inherit
else:
f.__doc__ = inherit + '\n\n' + f.__doc__
if kwargs:
# mapping interpolation
f.__doc__ = f.__doc__ % kwargs
if args:
try:
# inserting
f.__doc__ = f.__doc__ % args
except TypeError:
# appending
if f.__doc__ is None:
f.__doc__ = ''
f.__doc__ = f.__doc__ + '\n\n'+ '\n\n'.join(args)
return f
return mod_doc

I left out the dedentation for now, and it is untested. This can cover
lots of ground, I think it can be chained on itself:

@with_doc('append me', prepend='prepend me as well')
@with_doc(other_method)
@with_doc('prepend me %(prepend)s')

If it is not possible, or possible but messy because of dedentation or
other reasons, to pack everything into a single high-level decorator,
then maybe there should be a few like:

inherit_doc(fun) overwrite or prepend with fun's docstring
insert_doc(*args, **kwargs) interpolate
append_doc(*args)

but since these are high-level decorators, chaining decorators would
result in repeated calls to dedent.

Another thing to consider while cleaning this up is to not just put
the artist props into the kwdocd, but *anything* that needs
interpolating. So we could have one docstring.interpd into which all
keys 'Line2D', 'Patch', 'AvailableArrowstyles', 'PSD', 'scale_docs',
etc... Right now we have a hodge-podge of doc interpolation strings,
and it might make sense to simplify this by putting them all into a
single interp dict that can be used anywhere in mpl.

Jason, I hope we don't exhaust you with these suggestions -- this will
be a very nice cleanup and a big help for people using mpl in
installers like py2exe which strip out docs with the optimization
flags. But as Darren said we need to get this right and keep the
interface as simple as possible while preserving all the current
functionality. Thanks for all your efforts.

--
"In our description of nature, the purpose is not to disclose the real
essence of the phenomena but only to track down, so far as it is
possible, relations between the manifold aspects of our experience" -
Niels Bohr

"It is a bad habit of physicists to take their most successful
abstractions to be real properties of our world." - N. David Mermin

"Once we have granted that any physical theory is essentially only a
model for the world of experience, we must renounce all hope of
finding anything like the correct theory ... simply because the
totality of experience is never accessible to us." - Hugh Everett III

From: Darren Dale [mailto:dsdale24@…149…]

I appreciate how much time has gone into the patch, but this impacts
so much code I think it is important to really nail the
implementation.

Agreed

I think everything should be rolled up into a single
high level decorator if possible.

While I think this approach is useful for readability where a pattern is seen
repeated, trying to implement every matplotlib docstring manipulation into a
single, monolithic decorator has the potential to become messy. This is why
I've chosen to implement the same functionality in various components that can
(and should in some cases) be assembled into a single construct.

I offered a suggestion in the
tracker. Consider:

with_doc(*args, **kwargs):
    mod_doc(f):
        if args:
            if not isinstance(args[0], str):
                # inherit docstring from first argument
                inherit = args.pop(0).__doc__
                if f.__doc__ is None:
                    f.__doc__ = inherit
                else:
                    f.__doc__ = inherit + '\n\n' + f.__doc__
        if kwargs:
            # mapping interpolation
            f.__doc__ = f.__doc__ % kwargs
        if args:
            try:
                # inserting
                f.__doc__ = f.__doc__ % args
            except TypeError:
                 # appending
                 if f.__doc__ is None:
                     f.__doc__ = ''
                 f.__doc__ = f.__doc__ + '\n\n'+ '\n\n'.join(args)
        return f
    return mod_doc

I appreciate the suggested implementation. It helped inspire me with my
submitted patch, which I believe meets the same goals (or can with some
combination of some of the various decorators).

This suggested implementation however has a few drawbacks compared with the
submitted patch.

1) The form doesn't reflect the function. mod_doc indicates that the
documentation is being modified, but the function is implicit and has to be
reverse-engineered from the code. On the other hand, docstring.copy copies a
docstring, while docstring.Substitution performs substitution.
2) with_doc doesn't have a way to handle a mutable parameter set. That is,
all of the **kwargs or *args (in the second usage) must be present at the time
the decorator is created. In the case of the sub_args decorator in artist.py,
this isn't suitable. It would be possible to just create a new decorator
(i.e. with_doc(**artist.kwdocd)) every place of sub_args is used, but that
violates the DRY principle. The sub_args mutable decorator, on the other hand,
takes the place of artist.kwdocd by representing an object with purpose and
not just kwdocd data structure.
3) with_doc allows for both keyword and positional argument substitution.
This seems like a dangerous allowance.
4) Modular decorators can have delegated responsibility and be tested
separately.
5) with_doc hard-codes separators ('\n\n') in multiple places and doesn't
allow a different separator to be specified (if necessary).
6) The TypeError exception handler in the second usage of *args may trap more
exceptions than desired.
7) As you mentioned, it doesn't handle dedent. It's not clear to me where
dedent should be included in the logic to properly capture the needs of
matplotlib.
8) with_doc is largely addressing issues specifically around matplotlib. The
submitted patch provides reusable decorators which might be assembled in
creative ways not yet conceived.

Please understand, I'm trying to explain why the current implementation is
sound and not to criticize your contribution.

I left out the dedentation for now, and it is untested. This can cover
lots of ground, I think it can be chained on itself:

@with_doc('append me', prepend='prepend me as well')
@with_doc(other_method)
@with_doc('prepend me %(prepend)s')

The current code allows

@docstring.Substitution(prepend='prepend me as well')
@docstring.Appender('append me', join='\n\n')
@docstring.copy(other_method)
@docstring.Appender('prepend me %(prepend)s', join='\n\n')

While slightly more verbose, the second technique communicates clearly what is
happening and there's no implicit behavior going on (i.e. copy takes another
method while Appender takes a string). The default join could be '\n\n', but
I chose an empty string as default. If '\n\n' is more desirable, that could
certainly be made the default.

If it is not possible, or possible but messy because of dedentation or
other reasons, to pack everything into a single high-level decorator,
then maybe there should be a few like:

inherit_doc(fun) overwrite or prepend with fun's docstring

This is essentially the purpose of docstring.copy.

insert_doc(*args, **kwargs) interpolate

This is the behavior of docstring.Substitution (plus allows for mutable
parameters).

append_doc(*args)

This is docstring.Appender (except only allows one argument, and allows
separator to be supplied). If multiple args are require for appending, that
certainly could be implemented.

but since these are high-level decorators, chaining decorators would
result in repeated calls to dedent.

From that, high-level decorators could be assembled with the appropriate

dedent behavior included as well.

···

-----Original Message-----
On Thu, Aug 13, 2009 at 7:44 AM, John Hunter<jdh2358@...149...> wrote:
> On Wed, Aug 12, 2009 at 7:12 AM, John Hunter<jdh2358@...149...> > wrote:

Also, functools requires Python 2.5. Matplotlib supports Python 2.4.

···

-----Original Message-----
From: Darren Dale [mailto:dsdale24@…149…]
Sent: Thursday, 13 August, 2009 10:52
To: Gael Varoquaux
Cc: John Hunter; matplotlib development list; Eric Firing
Subject: Re: [matplotlib-devel] kwdoc processing with decorators

On Thu, Aug 13, 2009 at 10:24 AM, Gael > Varoquaux<gael.varoquaux@...427...> wrote:
>
> I have not followed the conversation, so please forgive me if I am
> talking bull**, but why are you not using functools.wraps? I have
found
> it is useful to make really sure that you are keeping all the
> properties of a function that you want to decorate.

I am aware of functools.wraps and have used it myself. So far we are
only modifying and returning the original function, not a wrapped
version of the original, so functools.wraps is not necessary.

Darren

John,

This seems like a good idea. I wanted to prove and vet the decorators first,
shake out any emergent issues, and then consider enhancements that the new
structure might enable.

While I was working through this, I was surprised when I saw how the kwdocd
was assembled from the various modules and magically seemed to have the
right values by the time the docstrings needed them... but after thinking
about it for a bit, it occurred to me that it probably works because when a
module depends on certain keys being present, it probably has already
imported the module that provides those keys. Therefore, synchronization
issues aren't really issues.

Would you like me to implement these suggestions?

Jason

···

-----Original Message-----
From: John Hunter [mailto:jdh2358@…149…]

Another thing to consider while cleaning this up is to not just put
the artist props into the kwdocd, but *anything* that needs
interpolating. So we could have one docstring.interpd into which all
keys 'Line2D', 'Patch', 'AvailableArrowstyles', 'PSD', 'scale_docs',
etc... Right now we have a hodge-podge of doc interpolation strings,
and it might make sense to simplify this by putting them all into a
single interp dict that can be used anywhere in mpl.

Jason, I hope we don't exhaust you with these suggestions -- this will
be a very nice cleanup and a big help for people using mpl in
installers like py2exe which strip out docs with the optimization
flags. But as Darren said we need to get this right and keep the
interface as simple as possible while preserving all the current
functionality. Thanks for all your efforts.

JDH

Jason R. Coombs wrote:

From: Darren Dale [mailto:dsdale24@…149…]

I appreciate how much time has gone into the patch, but this impacts
so much code I think it is important to really nail the
implementation.

Agreed

I think everything should be rolled up into a single
high level decorator if possible.

While I think this approach is useful for readability where a pattern is seen repeated, trying to implement every matplotlib docstring manipulation into a single, monolithic decorator has the potential to become messy. This is why I've chosen to implement the same functionality in various components that can (and should in some cases) be assembled into a single construct.

[...]

From that, high-level decorators could be assembled with the appropriate dedent behavior included as well.

Jason, John, Darren,

I am jumping in late, and with only superficial comments for the moment, at least. After scanning the latest patch and reading the emails up to this point, here are my reactions:

1) In general I like Jason's latest patch. It looks readable, flexible, and testable--but I haven't done any testing yet myself. I find the arguments in this email to which I am replying to be convincing, so I am in favor of Jason's modular approach rather than the monolithic alternative, to the extent that I understand both.

2) Question: how does this relate to all the work that Jouni did recently to fix pyplot docstrings?

3) Question: how does this affect startup time? Jouni tested two approaches to his work, and the decorator approach was significantly slower. I think that for many mpl applications (not to mention running backend_driver.py, which is already getting so slow as to deter its frequent use), startup time really matters. At one point, dedent was accounting for something like 30% of the overhead. Mike's optimization knocked it back to a tolerable level. (Avoiding dedent by keeping docstrings slid to the left in the source is not acceptable--it makes the source horrible to read.)

Ideally, all the docstring manipulations would be done once at the time of installation or of compilation to .pyc, not at every mpl startup. I think that doing it at compilation time is impossible, given python's fundamental design, so that leaves the installation time alternative. I don't have any more specific ideas at this point, though. If it turns out that the decorators don't add significantly to the startup time, then the question of alternatives is moot.

Eric

···

-----Original Message-----
On Thu, Aug 13, 2009 at 7:44 AM, John Hunter<jdh2358@...149...> wrote:

On Wed, Aug 12, 2009 at 7:12 AM, John Hunter<jdh2358@...149...> >> wrote:

While this is not impossible, it would make my building of the docs
more complicated, because there I rely on the runtime "hardcopy" rc
property to format rest docstrings. I could do a special installation
for doc building if it makes everyone else in the world's mpl loads
100x faster :slight_smile:

JDH

···

On Thu, Aug 13, 2009 at 1:08 PM, Eric Firing<efiring@...229...> wrote:

Ideally, all the docstring manipulations would be done once at the time of
installation or of compilation to .pyc, not at every mpl startup. I think
that doing it at compilation time is impossible, given python's fundamental
design, so that leaves the installation time alternative. I don't have any
more specific ideas at this point, though. If it turns out that the
decorators don't add significantly to the startup time, then the question of
alternatives is moot.

John Hunter wrote:

Ideally, all the docstring manipulations would be done once at the time of
installation or of compilation to .pyc, not at every mpl startup. I think
that doing it at compilation time is impossible, given python's fundamental
design, so that leaves the installation time alternative. I don't have any
more specific ideas at this point, though. If it turns out that the
decorators don't add significantly to the startup time, then the question of
alternatives is moot.

While this is not impossible, it would make my building of the docs
more complicated, because there I rely on the runtime "hardcopy" rc
property to format rest docstrings. I could do a special installation
for doc building if it makes everyone else in the world's mpl loads
100x faster :slight_smile:

JDH

I tested the startup time for r7480 before and after the patch, and the difference is quite small--of the order of a percent--so I have no objection to the patch on that account. Or, for that matter, on any other account. I would not object to applying it (or a modification, if there is still fine-tuning to be done) to the trunk. It seems to work fine. John, I assume you have tested doc building with the patch in place. I have not.

Eric

···

On Thu, Aug 13, 2009 at 1:08 PM, Eric Firing<efiring@...229...> wrote:

I'm about to upload a new patch that implements some of the ideas John and
Darren have sent. Would you mind running the performance tests against that
one also? This new change has the potential to increase performance drag.

Jason

···

-----Original Message-----
From: Eric Firing [mailto:efiring@…229…]
Sent: Thursday, 13 August, 2009 15:37
To: John Hunter
Cc: Jason R. Coombs; Darren Dale; matplotlib development list
Subject: Re: [matplotlib-devel] kwdoc processing with decorators

I tested the startup time for r7480 before and after the patch, and the
difference is quite small--of the order of a percent--so I have no
objection to the patch on that account. Or, for that matter, on any
other account. I would not object to applying it (or a modification,
if
there is still fine-tuning to be done) to the trunk. It seems to work
fine. John, I assume you have tested doc building with the patch in
place. I have not.

Eric

Jason R. Coombs wrote:

I'm about to upload a new patch that implements some of the ideas John and
Darren have sent. Would you mind running the performance tests against that
one also? This new change has the potential to increase performance drag.

Jason

I'll test it, but it might be a few hours.

Eric

Jason R. Coombs wrote:

I'm about to upload a new patch that implements some of the ideas John and
Darren have sent. Would you mind running the performance tests against that
one also? This new change has the potential to increase performance drag.

I tested it; performance still is not a problem.

firing@...340...:~/programs/py/mpl/tests$ python startuptime.py
average pylab startup time: 0.505041065216
efiring@...340...:~/programs/py/mpl/tests$ python startuptime.py
average pylab startup time: 0.508669295311

where the first number is r7480, and the second is after your patch #4.
The test script is attached.

Eric

startuptime.py (177 Bytes)

Jason R. Coombs wrote:

I'm about to upload a new patch that implements some of the ideas John and
Darren have sent. Would you mind running the performance tests against that
one also? This new change has the potential to increase performance drag.

Jason,

There is a problem with rev4, running "ipython -pylab":

In [1]:plot([1,2])

···

---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)

/home/efiring/<ipython console> in <module>()

/usr/local/lib/python2.6/dist-packages/matplotlib/docstring.pyc in <lambda>(target)
     334 # language" - GVR. I think functools might help when Python 2.5

     335 # is required.

--> 336 return lambda target: dedent(copy(source)(target))
     337 from matplotlib import cbook
     338

/usr/local/lib/python2.6/dist-packages/matplotlib/docstring.pyc in do_copy(target)
     422 def do_copy(target):
     423 if source.__doc__:
--> 424 target.__doc__ = source.__doc__
     425 return target
     426 return do_copy

AttributeError: 'list' object attribute '__doc__' is read-only

Eric

Oh, so you want _everything_ to work after the patch? GG

Thanks for reporting this. I'll track it down and get it fixed.

···

-----Original Message-----
From: Eric Firing [mailto:efiring@…229…]
Sent: Thursday, 13 August, 2009 21:33
To: Jason R. Coombs
Cc: matplotlib development list
Subject: Re: [matplotlib-devel] kwdoc processing with decorators

Jason R. Coombs wrote:

I'm about to upload a new patch that implements some of the ideas John and
Darren have sent. Would you mind running the performance tests against

that

one also? This new change has the potential to increase performance drag.

Jason,

There is a problem with rev4, running "ipython -pylab":

In [1]:plot([1,2])
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)

/home/efiring/<ipython console> in <module>()

/usr/local/lib/python2.6/dist-packages/matplotlib/docstring.pyc in
<lambda>(target)
     334 # language" - GVR. I think functools might help when
Python 2.5

     335 # is required.

--> 336 return lambda target: dedent(copy(source)(target))
     337 from matplotlib import cbook
     338

/usr/local/lib/python2.6/dist-packages/matplotlib/docstring.pyc in
do_copy(target)
     422 def do_copy(target):
     423 if source.__doc__:
--> 424 target.__doc__ = source.__doc__
     425 return target
     426 return do_copy

AttributeError: 'list' object attribute '__doc__' is read-only

Eric

Thanks again for pointing out the issue (to my embarrassment).

The rev5 patch addresses the issue. I had missed an essential parameter in
pyplot.autogen_docstring. I've tested this new patch, and I'm able to call
help(pyplot.plot) and execute pyplot.plot([1,2]) without any errors. I
believe this corrects the issue.

Please let me know if you encounter any additional issues.

Regards,
Jason

···

-----Original Message-----
From: Eric Firing [mailto:efiring@…229…]
Sent: Thursday, 13 August, 2009 21:33
To: Jason R. Coombs
Cc: matplotlib development list
Subject: Re: [matplotlib-devel] kwdoc processing with decorators

Jason,

There is a problem with rev4, running "ipython -pylab":