Using the docstring from one method to automatically overwrite that of another method

The problem: I have a class which contains a template method execute which calls another method _execute. Subclasses are supposed to overwrite _execute to implement some specific functionality. This functionality should be documented in the docstring of _execute. Advanced users can create their own subclasses to extend the library. However, another user dealing with such a subclass should only use execute, so he won't see the correct docstring if he uses help(execute).

Therefore it would be nice to modify the base class in such a way that in a subclass the docstring of execute is automatically replaced with that of _execute. Any ideas how this might be done?

I was thinking of metaclasses to do this, to make this completely transparent to the user.


Asked by: Julia303 | Posted: 01-10-2021






Answer 1

Well, if you don't mind copying the original method in the subclass, you can use the following technique.

import new

def copyfunc(func):
    return new.function(func.func_code, func.func_globals, func.func_name,
                        func.func_defaults, func.func_closure)

class Metaclass(type):
    def __new__(meta, name, bases, attrs):
        for key in attrs.keys():
            if key[0] == '_':
                skey = key[1:]
                for base in bases:
                    original = getattr(base, skey, None)
                    if original is not None:
                        copy = copyfunc(original)
                        copy.__doc__ = attrs[key].__doc__
                        attrs[skey] = copy
                        break
        return type.__new__(meta, name, bases, attrs)

class Class(object):
    __metaclass__ = Metaclass
    def execute(self):
        '''original doc-string'''
        return self._execute()

class Subclass(Class):
    def _execute(self):
        '''sub-class doc-string'''
        pass

Answered by: Cadie529 | Posted: 02-11-2021



Answer 2

Is there a reason you can't override the base class's execute function directly?

class Base(object):
    def execute(self):
        ...

class Derived(Base):
    def execute(self):
        """Docstring for derived class"""
        Base.execute(self)
        ...stuff specific to Derived...

If you don't want to do the above:

Method objects don't support writing to the __doc__ attribute, so you have to change __doc__ in the actual function object. Since you don't want to override the one in the base class, you'd have to give each subclass its own copy of execute:

class Derived(Base):
    def execute(self):
        return Base.execute(self)

    class _execute(self):
        """Docstring for subclass"""
        ...

    execute.__doc__= _execute.__doc__

but this is similar to a roundabout way of redefining execute...

Answered by: Lydia826 | Posted: 02-11-2021



Answer 3

Look at the functools.wraps() decorator; it does all of this, but I don't know offhand if you can get it to run in the right context

Answered by: Carina204 | Posted: 02-11-2021



Answer 4

Well the doc-string is stored in __doc__ so it wouldn't be too hard to re-assign it based on the doc-string of _execute after the fact.

Basically:

class MyClass(object):
    def execute(self):
        '''original doc-string'''
        self._execute()

class SubClass(MyClass):
    def _execute(self):
        '''sub-class doc-string'''
        pass

    # re-assign doc-string of execute
    def execute(self,*args,**kw):
        return MyClass.execute(*args,**kw)
    execute.__doc__=_execute.__doc__

Execute has to be re-declared to that the doc string gets attached to the version of execute for the SubClass and not for MyClass (which would otherwise interfere with other sub-classes).

That's not a very tidy way of doing it, but from the POV of the user of a library it should give the desired result. You could then wrap this up in a meta-class to make it easier for people who are sub-classing.

Answered by: Adrian666 | Posted: 02-11-2021



Answer 5

I agree that the simplest, most Pythonic way of approaching this is to simply redefine execute in your subclasses and have it call the execute method of the base class:

class Sub(Base):
    def execute(self):
        """New docstring goes here"""
        return Base.execute(self)

This is very little code to accomplish what you want; the only downside is that you must repeat this code in every subclass that extends Base. However, this is a small price to pay for the behavior you want.

If you want a sloppy and verbose way of making sure that the docstring for execute is dynamically generated, you can use the descriptor protocol, which would be significantly less code than the other proposals here. This is annoying because you can't just set a descriptor on an existing function, which means that execute must be written as a separate class with a __call__ method.

Here's the code to do this, but keep in mind that my above example is much simpler and more Pythonic:

class Executor(object):
    __doc__ = property(lambda self: self.inst._execute.__doc__)

    def __call__(self):
        return self.inst._execute()

class Base(object):
    execute = Executor()

class Sub(Base):
    def __init__(self):
        self.execute.inst = self

    def _execute(self):
        """Actually does something!"""
        return "Hello World!"

spam = Sub()
print spam.execute.__doc__  # prints "Actually does something!"
help(spam)                  # the execute method says "Actually does something!"

Answered by: Michelle372 | Posted: 02-11-2021



Similar questions

python - Tool for automatically check docstring style according to PEP257

Closed. This question does not meet Stack Overflow guid...


python - How to automatically generate unit testing routines from special syntax in method docstring / comment?

This is a mock-up of what I'm looking for: def is_even(a, b): """Returns True if both numbers are even. @AutoUnitTestTag: - (0,2) -> True - (2,1) -> False - (3,5) -> False """ return (a % 2 == 0 and b % 2 == 0) Is there a tool that could allow one to insert compact syntax-defined unit test...


debugging - Starting python debugger automatically on error

This is a question I have wondered about for quite some time, yet I have never found a suitable solution. If I run a script and I come across, let's say an IndexError, python prints the line, location and quick description of the error and exits. Is it possible to automatically start pdb when an error is encountered? I am not against having an extra import statement at the top of the file, nor a few extra lines of code.


python - PyQt: getting widgets to resize automatically in a QDialog

I'm having difficulty getting widgets in a QDialog resized automatically when the dialog itself is resized. In the following program, the textarea resizes automatically if you resize the main window. However, the textarea within the dialog stays the same size when the dialog is resized. Is there any way of making the textarea in the dialog resize automatically? I've tried using setSizePolicy(QSizePo...


python - Can I log into a web application automatically using a users windows logon?

On the intranet at my part time job (not IT related) there are various web applications that we use that do not require logging in explicitly. We are required to login to Windows obviously, and that then authenticates us some how. I'm wondering how this is done? Without worrying about security TOO much, how would I go about authenticating a user to a web application, utilizing the windows login information? I'd be ...


python - Is there a way to automatically generate a list of columns that need indexing?

The beauty of ORM lulled me into a soporific sleep. I've got an existing Django app with a lack of database indexes. Is there a way to automatically generate a list of columns that need indexing? I was thinking maybe some middleware that logs which columns are involved in WHERE clauses? but is there anything built into MySQL that might help?


How to automatically reload a python file when it is changed

If I make some changes to one of the files belonging to a running app, is there a way to tell the python runtime to automatically reload the module/file?


python - How to scroll automatically within a Tkinter message window

I wrote the following class for producing "monitoring" output within an extra window. Unfortunately it doesn't scroll automatically down to the most recent line. What is wrong? As I also have problems with Tkinter and ipython: how would an equivalent implementation with qt4 look like? Here is the code: import Tkinter class Monitor(object): @classmethod def write(cls...


python - How to automatically create postgis database for Django testing?

I'm trying to test my Django apps which run on a PostGIS database, by following the info in the Django testing docs. Normally I create a new database by copying a template: (as user postgres) createdb -T template_postgis -O lizard test_geodjango2 When I run ./manage.py test...


scripting - Automatically pressing a "submit" button using python

The bus company I use runs an awful website (Hebrew,English) which making a simple "From A to B timetable toda...


c# - Create a GUI from a XML schema automatically

I have to write a desktop application to edit data stored in a XML file. The format is defined by a XML schema file (.xsd). The format is quite complex. Are there tools which can generate a basic GUI automatically? It's not yet decided which language to use. I have experience in Python and C++ using wxWidgets and C# (.NET 1) using Windows Forms.


python - Threaded Django task doesn't automatically handle transactions or db connections?

I've got Django set up to run some recurring tasks in their own threads, and I noticed that they were always leaving behind unfinished database connection processes (pgsql "Idle In Transaction"). I looked through the Postgres logs and found that the transactions weren't being completed (no ROLLBACK). I tried using the various transaction decorators on my functions, no luck. I switched to manual transaction ...






Still can't find your answer? Check out these communities...



PySlackers | Full Stack Python | NHS Python | Pythonist Cafe | Hacker Earth | Discord Python



top