Closed Cediddi closed 1 year ago
Ah. That's a good suggestion. I can work on this. Give me sometime to look into this. Watch out this thread for updates.
Unfortunately I have not been able to respond actively but I am going to try to do now. Apologies for the delay.
Eh, i dont think it is possible unless pypa resolves pypa/setuptools#1139 .
I think the commit @isidentical mentioned is a good start. Celery does not come with a backend or broker driver out of the box (except ), you are supposed to install drivers either manually or by extras.
pip install celery
only comes with rabbitmq support (which is not celery's dependency, but kombu needs it). Documentation says, you should do pip install celery[redis,rabbitmq]
I think this is the way to go and docs should reflect that the drivers are optional.
I am cleaning up my github, the link is now broken but i kept diff,
diff --git a/setup.py b/setup.py
index a101a73..daa1eec 100644
--- a/setup.py
+++ b/setup.py
@@ -24,11 +24,6 @@ setup(
platforms=('Any',),
packages=find_packages(exclude=['tests']),
include_package_data=True,
- install_requires=[
- 'redis',
- 'python-etcd',
- 'pylibmc',
- ],
zip_safe = False,
classifiers = [
'Development Status :: 2 - Pre-Alpha',
@@ -41,5 +36,10 @@ setup(
tests_require=[
'nose',
'mock',
- ]
+ ],
+ extras_require={
+ 'redis': ['redis'],
+ 'etcd': ['python-etcd'],
+ 'memcached': ['pylibmc']
+ }
)
diff --git a/sherlock/__init__.py b/sherlock/__init__.py
index c88ca14..393caf6 100644
--- a/sherlock/__init__.py
+++ b/sherlock/__init__.py
@@ -227,50 +227,75 @@ Distributed Locking in Other Languages
* NodeJS - https://github.com/thedeveloper/warlock
'''
-import etcd
-import pylibmc
-import redis
-
+try:
+ from contextlib import suppress
+except ImportError:
+ from contextlib import contextmanager
+ @contextmanager
+ def suppress(exc):
+ try:
+ yield
+ except exc:
+ pass
class _Backends(object):
'''
A simple object that provides a list of available backends.
'''
- REDIS = {
- 'name': 'REDIS',
- 'library': 'redis',
- 'client_class': redis.StrictRedis,
- 'lock_class': 'RedisLock',
- 'default_args': (),
- 'default_kwargs': {},
- }
- ETCD = {
- 'name': 'ETCD',
- 'library': 'etcd',
- 'client_class': etcd.Client,
- 'lock_class': 'EtcdLock',
- 'default_args': (),
- 'default_kwargs': {},
- }
- MEMCACHED = {
- 'name': 'MEMCACHED',
- 'library': 'pylibmc',
- 'client_class': pylibmc.Client,
- 'lock_class': 'MCLock',
- 'default_args': (
- ['localhost'],
- ),
- 'default_kwargs': {
- 'binary': True,
- },
- }
-
- _valid_backends = (
- REDIS,
- ETCD,
- MEMCACHED,
- )
+ _valid_backends = []
+ _valid_backend_modules = {}
+
+ with suppress(ImportError):
+ import redis
+
+ REDIS = {
+ 'name': 'REDIS',
+ 'library': 'redis',
+ 'client_class': redis.StrictRedis,
+ 'lock_class': 'RedisLock',
+ 'default_args': (),
+ 'default_kwargs': {},
+ }
+
+ _valid_backends.append(REDIS)
+ _valid_backend_modules['redis'] = redis
+
+ with suppress(ImportError):
+ import etcd
+
+ ETCD = {
+ 'name': 'ETCD',
+ 'library': 'etcd',
+ 'client_class': etcd.Client,
+ 'lock_class': 'EtcdLock',
+ 'default_args': (),
+ 'default_kwargs': {},
+ }
+
+ _valid_backends.append(ETCD)
+ _valid_backend_modules['etcd'] = etcd
+
+ with suppress(ImportError):
+ import pylibmc
+
+ MEMCACHED = {
+ 'name': 'MEMCACHED',
+ 'library': 'pylibmc',
+ 'client_class': pylibmc.Client,
+ 'lock_class': 'MCLock',
+ 'default_args': (
+ ['localhost'],
+ ),
+ 'default_kwargs': {
+ 'binary': True,
+ },
+ }
+
+ _valid_backends.append(MEMCACHED)
+ _valid_backend_modules['pylibmc'] = pylibmc
+
+ _valid_backends = tuple(_valid_backends)
def register(self, name, lock_class, library, client_class,
default_args=(), default_kwargs={}):
diff --git a/sherlock/lock.py b/sherlock/lock.py
index a92ee02..9e2b2f3 100644
--- a/sherlock/lock.py
+++ b/sherlock/lock.py
@@ -9,14 +9,8 @@ __all__ = [
'LockException',
'LockTimeoutException',
'Lock',
- 'RedisLock',
- 'EtcdLock',
- 'MCLock'
]
-import etcd
-import pylibmc
-import redis
import time
import uuid
@@ -24,6 +18,18 @@ from . import backends
from . import _configuration
+def depends(module):
+ if module in backends._valid_backend_modules:
+ globals()[module] = backends._valid_backend_modules[module]
+
+ def wrapper(cls):
+ __all__.append(cls.__name__)
+ return cls
+
+ return wrapper
+ else:
+ return (lambda cls: None)
+
class LockException(Exception):
'''
Generic exception for Locks.
@@ -320,7 +326,7 @@ class Lock(BaseLock):
'Configure lock backend first.')
return self._lock_proxy.locked()
-
+@depends('redis')
class RedisLock(BaseLock):
'''
Implementation of lock with Redis as the backend for synchronization.
@@ -447,7 +453,7 @@ class RedisLock(BaseLock):
return False
return True
-
+@depends('etcd')
class EtcdLock(BaseLock):
'''
Implementation of lock with Etcd as the backend for synchronization.
@@ -562,7 +568,7 @@ class EtcdLock(BaseLock):
except etcd.EtcdKeyNotFound:
return False
-
+@depends('pylibmc')
class MCLock(BaseLock):
'''
Implementation of lock with Memcached as the backend for synchronization.
This is now implemented.
This is great. Thanks for the effort. Myself from 5 years ago would be thrilled. I may give sherlock another go in a different project now :)
I want to install sherlock but I'll not use memcache as my backend, I'll use redis exclusively. I wish there was a way to select our backends like in celery. pylibmc depends on
memcached.h
file.