Skip to content

Instantly share code, notes, and snippets.

@Ricocotam
Forked from wowkin2/SingletonMongoClient.py
Created December 15, 2020 07:46
Show Gist options
  • Save Ricocotam/f41372316c418ca2a2b5a63afddfeb88 to your computer and use it in GitHub Desktop.
Save Ricocotam/f41372316c418ca2a2b5a63afddfeb88 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).
"""
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