I'm using a decorator for singletons in python, implemented as shown below.
I'd like to have the pydoc of the decorated class being exactly the same as the pydoc of the non decorated class, but I don't find how:
Without the getSingletonInstance.__doc__ = cls.__doc__
line, the pydoc of the decorated class gives the pydoc of the singleton
function.
With the getSingletonInstance.__doc__ = cls.__doc__
line, the pydoc of the decorated class gives only the "top level" docstring.
How can I proceed?
Thanks.
def singleton(cls):
"""A singleton decorator
Warnings
--------
Singleton gdecorated calsses cannot be inhehited
Example
-------
>>> from decorators import singleton
>>> @singleton
... class SingletonDemo():
... pass
>>> d1 = SingletonDemo()
>>> d1.a = 0xCAFE
>>> d2 = SingletonDemo()
>>> id(d1) == id(d2)
True
>>> d1 == d2
True
>>> d2.a == 0xCAFE
True
References
----------
See case 2 of https://www.python.org/dev/peps/pep-0318/#examples
"""
_instances = {}
def getSingletonInstance():
if cls not in _instances:
_instances[cls] = cls()
return _instances[cls]
getSingletonInstance.__doc__ = cls.__doc__
return getSingletonInstance
Try using functools.wraps
:
import functools
def wrapper(cls):
_instances = {}
class inner(cls):
def __new__(subcls):
if subcls not in _instances:
_instances[subcls] = object.__new__(subcls)
return _instances[subcls]
inner.__doc__=cls.__doc__
return inner
@wrapper
class A(object):
"""Example Docstring"""
def method(self):
"""Method Docstring"
A.__doc__
# "Example Docstring"
A.method.__doc__
# "Method Docstring"
Answer summarizing all the discussions, with example. Thanks a lot to everybody.
This solution:
Limitations:
Solution: def singleton(cls):
"""A singleton decorator
Warnings
--------
Singleton decorated classes cannot be inhehited
Example
-------
>>> import abc
>>>
>>> @singleton
... class A():
... "Ad-hoc documentation of class A"
... def __init__(self):
... "Ad-hoc documentation of class A constructor"
... print("constructor called")
... self.x = None
... @classmethod
... def cm(cls):
... "a class method"
... print("class method called")
... def im(self):
... "an instance method"
... print("instance method called")
... @staticmethod
... def sm():
... "a static method"
... print("static method called")
...
>>> @singleton
... class P(abc.ABCMeta):
... @abc.abstractmethod
... def __init__(self):
... pass
...
>>> class C(P):
... def __init__(self):
... print("C1 constructor called")
...
>>> a1 = A()
constructor called
>>> a1.x = 0xCAFE
>>> a1.x
51966
>>> a2 = A()
>>> a2.x
51966
>>> a1.x == a2.x
True
>>> a1 == a2
True
>>> id(a1) == id(a2)
True
>>> type(a1) == type(a2)
True
>>> isinstance(a1, A)
True
>>> ta1 = type(a1)
>>> issubclass(ta1, A)
True
>>> A.cm()
class method called
>>> a1.cm()
class method called
>>> A.sm()
static method called
>>> a1.sm()
static method called
>>> a1.im()
instance method called
>>> try:
... C()
... except Exception as e:
... type(e)
...
<class 'TypeError'>
"""
_instances = {}
_constructorCalled = []
class inner(cls):
def __new__(subcls):
if subcls not in _instances:
_instances[subcls] = cls.__new__(subcls)
return _instances[subcls]
def __init__(self):
if type(self) not in _constructorCalled:
cls.__init__(self)
_constructorCalled.append(type(self))
__init__.__doc__ = cls.__init__.__doc__
__new__.__doc__ = cls.__new__.__doc__
if __new__.__doc__ == (
"Create and return a new object. "
"See help(type) for accurate signature."
):
__new__.__doc__ = "Returns a singleton instance"
inner.__doc__ = cls.__doc__
return inner
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.