-
-
Save AndersonFirmino/15587c4997af32280fdb70c470838586 to your computer and use it in GitHub Desktop.
Python Singleton with parameters (so the same parameters get you the same object) with support to default arguments and passing arguments as kwargs (but no support for pure kwargs).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Python Singleton with parameters (so the same parameters get you the same object) | |
with support to default arguments and passing arguments as kwargs (but no support for pure kwargs). | |
And implementation for MongoClient class from pymongo package. | |
""" | |
from pymongo import MongoClient | |
import inspect | |
class Singleton(type): | |
""" Simple Singleton that keep only one value for all instances | |
""" | |
def __init__(cls, name, bases, dic): | |
super(Singleton, cls).__init__(name, bases, dic) | |
cls.instance = None | |
def __call__(cls, *args, **kwargs): | |
if cls.instance is None: | |
cls.instance = super(Singleton, cls).__call__(*args, **kwargs) | |
return cls.instance | |
class SingletonArgs(type): | |
""" Singleton that keep single instance for single set of arguments. E.g.: | |
assert SingletonArgs('spam') is not SingletonArgs('eggs') | |
assert SingletonArgs('spam') is SingletonArgs('spam') | |
""" | |
_instances = {} | |
_init = {} | |
def __init__(cls, name, bases, dct): | |
cls._init[cls] = dct.get('__init__', None) | |
def __call__(cls, *args, **kwargs): | |
init = cls._init[cls] | |
if init is not None: | |
key = (cls, frozenset( | |
inspect.getcallargs(init, None, *args, **kwargs).items())) | |
else: | |
key = cls | |
if key not in cls._instances: | |
cls._instances[key] = super(SingletonArgs, cls).__call__(*args, **kwargs) | |
return cls._instances[key] | |
class SingletonMongoClient(object): | |
""" Class based on Singleton type to work with MongoDB connections | |
""" | |
__metaclass__ = SingletonArgs | |
def __init__(self, url, db_name=None): | |
if db_name: | |
self.connection = MongoClient(url)[db_name] | |
else: | |
self.connection = MongoClient(url).get_default_database() | |
def connection(self): | |
return self.connection | |
def db_init(db_name=None): | |
url = 'mongodb://localhost:27017/' | |
c = SingletonMongoClient(url, db_name).connection | |
return c | |
def tests(): | |
class A(object): | |
__metaclass__ = SingletonArgs | |
FOO = 'bar' | |
assert A() is A() | |
class B(object): | |
__metaclass__ = SingletonArgs | |
def __init__(self, key): | |
self.key = key | |
assert B('key1') is B('key1') | |
assert B('key1') is not B('key2') | |
class C(object): | |
__metaclass__ = SingletonArgs | |
def __init__(self, key=None): | |
self.key = key | |
assert C() is C() | |
assert C() is C(None) | |
assert C(None) is C(key=None) | |
assert C() is C(key=None) | |
assert C() is not C('key') | |
assert C('key') is C('key') | |
assert C('key') is C(key='key') | |
assert C('key1') is not C(key='key2') | |
assert C(key='key1') is not C(key='key2') | |
class D(object): | |
__metaclass__ = SingletonArgs | |
def __init__(self): | |
pass | |
class E(object): | |
__metaclass__ = SingletonArgs | |
def __init__(self): | |
pass | |
assert D() is not E() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment