Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I programmatically set the docstring?

I have a wrapper function that returns a function. Is there a way to programmatically set the docstring of the returned function? If I could write to __doc__ I'd do the following:

def wrapper(a):     def add_something(b):        return a + b     add_something.__doc__ = 'Adds ' + str(a) + ' to `b`'     return add_something 

Then I could do

>>> add_three = wrapper(3) >>> add_three.__doc__ 'Adds 3 to `b` 

However, since __doc__ is read-only, I can't do that. What's the correct way?


Edit: Ok, I wanted to keep this simple, but of course this is not what I'm actually trying to do. Even though in general __doc__ is writeable in my case it isn't.

I am trying to create testcases for unittest automatically. I have a wrapper function that creates a class object that is a subclass of unittest.TestCase:

import unittest def makeTestCase(filename, my_func):     class ATest(unittest.TestCase):         def testSomething(self):             # Running test in here with data in filename and function my_func             data  = loadmat(filename)             result = my_func(data)             self.assertTrue(result > 0)      return ATest 

If I create this class and try to set the docstring of testSomething I get an error:

>>> def my_func(): pass >>> MyTest = makeTestCase('some_filename', my_func) >>> MyTest.testSomething.__doc__ = 'This should be my docstring' AttributeError: attribute '__doc__' of 'instancemethod' objects is not writable 
like image 663
oceanhug Avatar asked Oct 30 '10 02:10

oceanhug


2 Answers

An instancemethod gets its docstring from its __func__. Change the docstring of __func__ instead. (The __doc__ attribute of functions are writeable.)

>>> class Foo(object): ...     def bar(self): ...         pass ... >>> Foo.bar.__func__.__doc__ = "A super docstring" >>> help(Foo.bar) Help on method bar in module __main__:  bar(self) unbound __main__.Foo method     A super docstring  >>> foo = Foo() >>> help(foo.bar) Help on method bar in module __main__:  bar(self) method of __main__.Foo instance     A super docstring 

From the 2.7 docs:

User-defined methods

A user-defined method object combines a class, a class instance (or None) and any callable object (normally a user-defined function).

Special read-only attributes: im_self is the class instance object, im_func is the function object; im_class is the class of im_self for bound methods or the class that asked for the method for unbound methods; __doc__ is the method’s documentation (same as im_func.__doc__); __name__ is the method name (same as im_func.__name__); __module__ is the name of the module the method was defined in, or None if unavailable.

Changed in version 2.2: im_self used to refer to the class that defined the method.

Changed in version 2.6: For 3.0 forward-compatibility, im_func is also available as __func__, and im_self as __self__.

like image 66
hwiechers Avatar answered Sep 28 '22 01:09

hwiechers


I would pass the docstring into the factory function and use type to manually construct the class.

def make_testcase(filename, myfunc, docstring):     def test_something(self):         data = loadmat(filename)         result = myfunc(data)         self.assertTrue(result > 0)      clsdict = {'test_something': test_something,                '__doc__': docstring}     return type('ATest', (unittest.TestCase,), clsdict)  MyTest = makeTestCase('some_filename', my_func, 'This is a docstring') 
like image 37
aaronasterling Avatar answered Sep 27 '22 23:09

aaronasterling