diff --git a/omniduct/_version.py b/omniduct/_version.py index a70a2cf..59b1955 100644 --- a/omniduct/_version.py +++ b/omniduct/_version.py @@ -72,6 +72,11 @@ 'pexpect', # Command line handling (including smartcard activation) ], + # Wrappers + 'redis': [ + 'redis', # Primary Client + ], + # Rest clients 'rest': [ 'requests', # Library to handle underlying REST queries diff --git a/omniduct/duct.py b/omniduct/duct.py index f683554..82cc228 100644 --- a/omniduct/duct.py +++ b/omniduct/duct.py @@ -292,7 +292,7 @@ class name if not specified). atexit.register(self.disconnect) self.__prepared = False - self.__getting = False + self.__preparing = False self.__disconnecting = False self.__cached_auth = {} self.__prepreparation_values = {} @@ -346,16 +346,16 @@ def for_protocol(cls, key): def __getattribute__(self, key): try: if (not object.__getattribute__(self, '_Duct__prepared') - and not object.__getattribute__(self, '_Duct__getting') + and not object.__getattribute__(self, '_Duct__preparing') and not object.__getattribute__(self, '_Duct__disconnecting') and key in object.__getattribute__(self, '_Duct__prepare_triggers')): - object.__setattr__(self, '_Duct__getting', True) + object.__setattr__(self, '_Duct__preparing', True) object.__getattribute__(self, 'prepare')() - object.__setattr__(self, '_Duct__getting', False) + object.__setattr__(self, '_Duct__preparing', False) except AttributeError: pass except Exception as e: - object.__setattr__(self, '_Duct__getting', False) + object.__setattr__(self, '_Duct__preparing', False) raise_with_traceback(e) return object.__getattribute__(self, key) diff --git a/omniduct/protocols.py b/omniduct/protocols.py index b505595..162283c 100644 --- a/omniduct/protocols.py +++ b/omniduct/protocols.py @@ -13,3 +13,4 @@ from .remotes.ssh import SSHClient from .remotes.ssh_paramiko import ParamikoSSHClient from .restful.base import RestClient +from .wrappers.redis import RedisClient diff --git a/omniduct/wrappers/__init__.py b/omniduct/wrappers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/omniduct/wrappers/base.py b/omniduct/wrappers/base.py new file mode 100644 index 0000000..f94d605 --- /dev/null +++ b/omniduct/wrappers/base.py @@ -0,0 +1,24 @@ +from abc import abstractmethod +from omniduct.duct import Duct +from omniduct.utils.docs import quirk_docs + + +class WrapperClient(Duct): + + DUCT_TYPE = Duct.Type.OTHER + + @quirk_docs('_init', mro=True) + def __init__(self, **kwargs): + Duct.__init_with_kwargs__(self, kwargs, port=self.DEFAULT_PORT) + self._init(**kwargs) + + @abstractmethod + def _init(self): + pass + + @property + def wrapped_field(self): + raise NotImplementedError + + def __getattr__(self, key): + return getattr(object.__getattribute__(self, self.wrapped_field), key) diff --git a/omniduct/wrappers/redis.py b/omniduct/wrappers/redis.py new file mode 100644 index 0000000..9a6bb0c --- /dev/null +++ b/omniduct/wrappers/redis.py @@ -0,0 +1,49 @@ +from __future__ import absolute_import + +import redis +from omniduct.utils.debug import logger +from .base import WrapperClient + +from omniduct.utils.magics import (MagicsProvider, process_line_arguments, + process_line_cell_arguments) + + +class RedisClient(WrapperClient, MagicsProvider): + """ + This Duct connects to a redis database server using the `redis` python library. + """ + PROTOCOLS = ['redis'] + DEFAULT_PORT = 6379 + + def _init(self): + self._redis_connection = None + + def _connect(self): + self._redis_connection = redis.Redis(self.host, self.port) + + def _is_connected(self): + return hasattr(self, '_redis_connection') and self._redis_connection is not None + + def _disconnect(self): + logger.info('Disconnecting from Redis database ...') + self._redis_connection = None + + @property + def wrapped_field(self): + return '_redis_connection' + + def _register_magics(self, base_name): + """ + The following magic functions will be registered (assuming that + the base name is chosen to be 'redis'): + - Cell Magics: + - `%%redis`: Run the provided command + + Documentation for these magics is provided online. + """ + from IPython.core.magic import register_cell_magic + + @register_cell_magic(base_name) + @process_line_cell_arguments + def execute_command_magic(*args, **kwargs): + return self.execute_command(*args, **kwargs)