/usr/lib/python2.7/dist-packages/PythonCard/singleton.py is in python-pythoncard 0.8.2-5.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 | """
__version__ = "$Revision: 1.2 $"
__date__ = "$Date: 2004/04/16 14:55:00 $"
"""
"""
A Python Singleton mixin class that makes use of some of the ideas
found at http://c2.com/cgi/wiki?PythonSingleton. Just inherit
from it and you have a singleton. No code is required in
subclasses to create singleton behavior -- inheritance from
Singleton is all that is needed.
Assume S is a class that inherits from Singleton. Useful behaviors
are:
1) Getting the singleton:
S.getInstance()
returns the instance of S. If none exists, it is created.
2) The usual idiom to construct an instance by calling the class, i.e.
S()
is disabled for the sake of clarity. If it were allowed, a programmer
who didn't happen notice the inheritance from Singleton might think he
was creating a new instance. So it is felt that it is better to
make that clearer by requiring the call of a class method that is defined in
Singleton. An attempt to instantiate via S() will restult in an SingletonException
being raised.
3) If S.__init__(.) requires parameters, include them in the
first call to S.getInstance(.). If subsequent calls have parameters,
a SingletonException is raised.
4) As an implementation detail, classes that inherit
from Singleton may not have their own __new__
methods. To make sure this requirement is followed,
an exception is raised if a Singleton subclass includ
es __new__. This happens at subclass instantiation
time (by means of the MetaSingleton metaclass.
By Gary Robinson, grobinson@transpose.com. No rights reserved --
placed in the public domain -- which is only reasonable considering
how much it owes to other people's version which are in the
public domain. The idea of using a metaclass came from
a comment on Gary's blog (see
http://www.garyrobinson.net/2004/03/python_singleto.html#comments).
Not guaranteed to be fit for any particular purpose.
RDS - 2004-04-16
To make a class a Singleton, inhert from singleton.Singleton.
Call <Class>.getInstance() to get the single instance of <Class>.
Any arguments passed to <Class>.getInstance() will be passed on
to your <Class>.__init__.
"""
class SingletonException(Exception):
pass
class MetaSingleton(type):
def __new__(metaclass, strName, tupBases, dict):
if dict.has_key('__new__'):
raise SingletonException, 'Can not override __new__ in a Singleton'
return super(MetaSingleton,metaclass).__new__(metaclass, strName, tupBases, dict)
def __call__(cls, *lstArgs, **dictArgs):
raise SingletonException, 'Singletons may only be instantiated through getInstance()'
class Singleton(object):
__metaclass__ = MetaSingleton
def getInstance(cls, *lstArgs):
"""
Call this to instantiate an instance or retrieve the existing instance.
If the singleton requires args to be instantiated, include them the first
time you call getInstance.
"""
if cls._isInstantiated():
if len(lstArgs) != 0:
raise SingletonException, 'If no supplied args, singleton must already be instantiated, or __init__ must require no args'
else:
if len(lstArgs) != cls._getConstructionArgCountNotCountingSelf():
raise SingletonException, 'If the singleton requires __init__ args, supply them on first instantiation'
instance = cls.__new__(cls)
instance.__init__(*lstArgs)
cls.cInstance = instance
return cls.cInstance
getInstance = classmethod(getInstance)
def _isInstantiated(cls):
return hasattr(cls, 'cInstance')
_isInstantiated = classmethod(_isInstantiated)
def _getConstructionArgCountNotCountingSelf(cls):
return cls.__init__.im_func.func_code.co_argcount - 1
_getConstructionArgCountNotCountingSelf = classmethod(_getConstructionArgCountNotCountingSelf)
def _forgetClassInstanceReferenceForTesting(cls):
"""
This is designed for convenience in testing -- sometimes you
want to get rid of a singleton during test code to see what
happens when you call getInstance() under a new situation.
To really delete the object, all external references to it
also need to be deleted.
"""
delattr(cls,'cInstance')
_forgetClassInstanceReferenceForTesting = classmethod(_forgetClassInstanceReferenceForTesting)
if __name__ == '__main__':
import unittest
class PublicInterfaceTest(unittest.TestCase):
def testReturnsSameObject(self):
"""
Demonstrates normal use -- just call getInstance and it returns a singleton instance
"""
class A(Singleton):
def __init__(self):
super(A, self).__init__()
a1 = A.getInstance()
a2 = A.getInstance()
self.assertEquals(id(a1), id(a2))
def testInstantiateWithMultiArgConstructor(self):
"""
If the singleton needs args to construct, include them in the first
call to get instances.
"""
class B(Singleton):
def __init__(self, arg1, arg2):
super(B, self).__init__()
self.arg1 = arg1
self.arg2 = arg2
b1 = B.getInstance('arg1 value', 'arg2 value')
b2 = B.getInstance()
self.assertEquals(b1.arg1, 'arg1 value')
self.assertEquals(b1.arg2, 'arg2 value')
self.assertEquals(id(b1), id(b2))
def testTryToInstantiateWithoutNeededArgs(self):
class B(Singleton):
def __init__(self, arg1, arg2):
super(B, self).__init__()
self.arg1 = arg1
self.arg2 = arg2
self.assertRaises(SingletonException, B.getInstance)
def testTryToInstantiateWithoutGetInstance(self):
"""
Demonstrates that singletons can ONLY be instantiated through
getInstance, as long as they call Singleton.__init__ during construction.
If this check is not required, you don't need to call Singleton.__init__().
"""
class A(Singleton):
def __init__(self):
super(A, self).__init__()
self.assertRaises(SingletonException, A)
def testDontAllowNew(self):
def instantiatedAnIllegalClass():
class A(Singleton):
def __init__(self):
super(A, self).__init__()
def __new__(metaclass, strName, tupBases, dict):
return super(MetaSingleton,metaclass).__new__(metaclass, strName, tupBases, dict)
self.assertRaises(SingletonException, instantiatedAnIllegalClass)
def testDontAllowArgsAfterConstruction(self):
class B(Singleton):
def __init__(self, arg1, arg2):
super(B, self).__init__()
self.arg1 = arg1
self.arg2 = arg2
b1 = B.getInstance('arg1 value', 'arg2 value')
self.assertRaises(SingletonException, B, 'arg1 value', 'arg2 value')
unittest.main()
|