From 656bea17beed1b9d718b756267c1753d6157558d Mon Sep 17 00:00:00 2001 From: Dwight Hubbard Date: Wed, 4 May 2016 17:27:43 -0700 Subject: [PATCH 1/4] Deal with dbfilenames that have spaces in them. --- redislite/configuration.py | 35 +++++++++++++++++++++++----- tests/test_configuration.py | 46 +++++++++++++++++++++++++++---------- 2 files changed, 63 insertions(+), 18 deletions(-) diff --git a/redislite/configuration.py b/redislite/configuration.py index b06d61c..d86a542 100644 --- a/redislite/configuration.py +++ b/redislite/configuration.py @@ -88,6 +88,29 @@ def settings(**kwargs): return new_settings +def config_line(setting, value): + """ + Generate a single configuration line based on the setting and value + + Parameters + ---------- + setting : str + The configuration setting + + value : str + The value for the configuration setting + + Returns + ------- + str + The configuration line based on the setting and value + """ + if setting in ['dbfilename', 'dbdir']: + if ' ' in value and '"' not in value: + value = '"' + value + '"' + return '{setting} {value}'.format(setting=setting, value=value) + + def config(**kwargs): """ Generate a redis configuration file based on the passed arguments @@ -109,13 +132,13 @@ def config(**kwargs): if config_dict[key]: if isinstance(config_dict[key], list): for item in config_dict[key]: - configuration += '{key} {value}\n'.format( - key=key, value=item - ) + configuration += config_line( + setting=key, value=item + ) + '\n' else: - configuration += '{key} {value}\n'.format( - key=key, value=config_dict[key] - ) + configuration += config_line( + setting=key, value=config_dict[key] + ) + '\n' else: del config_dict[key] logger.debug('Using configuration: %s', configuration) diff --git a/tests/test_configuration.py b/tests/test_configuration.py index d53e98c..6a7fb4b 100644 --- a/tests/test_configuration.py +++ b/tests/test_configuration.py @@ -12,7 +12,11 @@ import inspect import logging import os +import psutil import redislite +import redislite.configuration +import tempfile +import shutil import unittest @@ -36,8 +40,6 @@ def _redis_server_processes(self): by the current user. :return: """ - import psutil - processes = [] for proc in psutil.process_iter(): try: @@ -55,11 +57,15 @@ def _log_redis_pid(self, connection): ) def setUp(self): + self.tempdir = tempfile.mkdtemp() logger.info( 'Start Child processes: %d', self._redis_server_processes() ) def tearDown(self): + if os.path.exists(self.tempdir) and 'tmp' in self.tempdir: + shutil.rmtree(self.tempdir) + self.tempdir = None logger.info( 'End Child processes: %d', self._redis_server_processes() ) @@ -68,14 +74,17 @@ def test_debug(self): import redislite.debug redislite.debug.print_debug_info() + def test_configuration_config_line(self): + result = redislite.configuration.config_line( + 'dbfilename', 'test file.db' + ) + self.assertEqual('dbfilename "test file.db"', result) + def test_configuration_config(self): - import redislite.configuration result = redislite.configuration.config() self.assertIn('\ndaemonize yes', result) - def test_configuration_modify_defaults(self): - import redislite.configuration result = redislite.configuration.config(daemonize="no") self.assertIn('\ndaemonize no', result) @@ -86,7 +95,6 @@ def test_configuration_modify_defaults(self): def test_configuration_settings(self): - import redislite.configuration result = redislite.configuration.settings() del result['save'] # Save is a list which doesn't work with set result_set = set(result.items()) @@ -105,20 +113,34 @@ def test_configuration_settings(self): def test_configuration_config_db(self): - import redislite.configuration + pidfile = os.path.join(self.tempdir, 'test.pid') + unixsocket = os.path.join(self.tempdir, 'redis.socket') result = redislite.configuration.config( - pidfile='/var/run/redislite/test.pid', - unixsocket='/var/run/redislite/redis.socket', - dbdir=os.getcwd(), + pidfile=pidfile, + unixsocket= unixsocket, + dbdir=self.tempdir, dbfilename='test.db', ) self.assertIn('\ndaemonize yes', result) - self.assertIn('\npidfile /var/run/redislite/test.pid', result) + self.assertIn('\npidfile ' + pidfile, result) self.assertIn('\ndbfilename test.db', result) + def test_configuration_config_db_with_space(self): + pidfile = os.path.join(self.tempdir, 'test.pid') + unixsocket = os.path.join(self.tempdir, 'redis.socket') + result = redislite.configuration.config( + pidfile=pidfile, + unixsocket=unixsocket, + dbdir=self.tempdir, + dbfilename='test space.db', + ) + + self.assertIn('\ndaemonize yes', result) + self.assertIn('\npidfile ' + pidfile, result) + self.assertIn('\ndbfilename "test space.db"', result) + def test_configuration_config_slave(self): - import redislite.configuration result = redislite.configuration.config( pidfile='/var/run/redislite/test.pid', unixsocket='/var/run/redislite/redis.socket', From 65e334f17e7af53fe2643ecf41dd4ccc5fa038df Mon Sep 17 00:00:00 2001 From: Dwight Hubbard Date: Thu, 5 May 2016 12:34:24 -0700 Subject: [PATCH 2/4] Deal with dbfilenames that have spaces in them. Add redis-server logging in all cases where the redis server fails to start. Add a new redis_log_tail method to allow tailing the redis server log file and add a redis_log attribute that returns the redis server log as a string. Fix test coverage issues. --- redislite/client.py | 67 +++++++++++++++++++++++++++++++++----- redislite/configuration.py | 16 ++++----- tests/test_client.py | 36 ++++++++++++++++++++ tests/test_patch.py | 51 ++++++++++++++++++++++++----- tests/test_slave.py | 17 +++------- 5 files changed, 149 insertions(+), 38 deletions(-) diff --git a/redislite/client.py b/redislite/client.py index e56673a..38504e4 100644 --- a/redislite/client.py +++ b/redislite/client.py @@ -67,7 +67,7 @@ def _cleanup(self, sys_modules=None): Stop the redis-server for this instance if it's running :return: """ - if sys_modules: + if sys_modules: # pragma: no cover import sys sys.modules.update(sys_modules) @@ -81,7 +81,7 @@ def _cleanup(self, sys_modules=None): ) # noinspection PyUnresolvedReferences logger.debug( - 'Shutting down redis server with pid of %d', self.pid + 'Shutting down redis server with pid of %r', self.pid ) self.shutdown() self.socket_file = None @@ -178,10 +178,7 @@ def _start_redis(self): rc = subprocess.call(command) if rc: # pragma: no cover logger.debug('The binary redis-server failed to start') - redis_log = os.path.join(self.redis_dir, 'redis.log') - if os.path.exists(redis_log): - with open(redis_log) as file_handle: - logger.debug(file_handle.read()) + logger.debug('Redis Server log:\n%s', self.redis_log) raise RedisLiteException('The binary redis-server failed to start') # Wait for Redis to start @@ -192,11 +189,13 @@ def _start_redis(self): break time.sleep(.1) if timeout: # pragma: no cover + logger.debug('Redis Server log:\n%s', self.redis_log) raise RedisLiteServerStartError( 'The redis-server process failed to start' ) if not os.path.exists(self.socket_file): # pragma: no cover + logger.debug('Redis Server log:\n%s', self.redis_log) raise RedisLiteException( 'Redis socket file %s is not present' % self.socket_file ) @@ -382,7 +381,6 @@ def __init__(self, *args, **kwargs): self.settingregistryfile = os.path.join( self.dbdir, self.dbfilename + '.settings' ) - self._start_redis() kwargs['unix_socket_path'] = self.socket_file @@ -396,6 +394,60 @@ def __init__(self, *args, **kwargs): def __del__(self): self._cleanup() # pragma: no cover + def redis_log_tail(self, lines=1, width=80): + """ + The redis log output + + + Parameters + ---------- + lines : int, optional + Number of lines from the end of the logfile to return, a value of + 0 will return all lines, default=1 + + width : int, optional + The expected average width of a log file line, this is used to + determine the chunksize of the seek operations, default=80 + + Returns + ------- + list + List of strings containing the lines from the logfile requested + """ + chunksize = lines * width + + if not os.path.exists(self.logfile): + return [] + + with open(self.logfile) as log_handle: + if lines == 0: + return [l.strip() for l in log_handle.readlines()] + log_handle.seek(0, 2) + log_size = log_handle.tell() + if log_size == 0: + logger.debug('Logfile %r is empty', self.logfile) + return [] + data = [] + for increment in range(1, int(log_size / chunksize) + 1): + seek_location = max(chunksize * increment, 0) + log_handle.seek(seek_location, 0) + data = log_handle.readlines() + if len(data) >= lines: + return [l.strip() for l in data[-lines:]] + return [l.strip() for l in data] + + @property + def redis_log(self): + """ + Redis server log content as a string + + Returns + ------- + str + Log contents + """ + return os.linesep.join(self.redis_log_tail(lines=0)) + @property def db(self): """ @@ -431,7 +483,6 @@ def pid(self): return int(pid) return 0 # pragma: no cover - class Redis(RedisMixin, redis.Redis): """ This class provides an enhanced version of the :class:`redis.Redis()` class diff --git a/redislite/configuration.py b/redislite/configuration.py index d86a542..6e00b19 100644 --- a/redislite/configuration.py +++ b/redislite/configuration.py @@ -18,6 +18,7 @@ 'appendonly': 'no', 'appendfilename': '"appendonly.aof"', 'appendfsync': 'everysec', + 'aof-load-truncated': 'yes', 'auto-aof-rewrite-percentage': '100', 'auto-aof-rewrite-min-size': '64mb', 'bind': None, @@ -25,15 +26,13 @@ 'databases': '16', 'dbdir': './', 'dbfilename': 'redis.db', + 'loglevel': 'notice', + 'logfile' : 'redis.log', 'pidfile': '/var/run/redislite/redis.pid', 'port': '0', 'save': ['900 1', '300 100', '60 200', '15 1000'], 'tcp-backlog': '511', - 'unixsocket': '/var/run/redislite/redis.socket', - 'unixsocketperm': '700', 'tcp-keepalive': '0', - 'loglevel': 'notice', - 'logfile' : 'redis.log', 'stop-writes-on-bgsave-error': 'yes', 'rdbcompression': 'yes', 'rdbchecksum': 'yes', @@ -43,7 +42,6 @@ 'repl-disable-tcp-nodelay': 'no', 'slave-priority': '100', 'no-appendfsync-on-rewrite': 'no', - 'aof-load-truncated': 'yes', 'lua-time-limit': '5000', 'slowlog-log-slower-than': '10000', 'slowlog-max-len': '128', @@ -54,10 +52,12 @@ 'list-max-ziplist-entries': '512', 'list-max-ziplist-value': '64', 'set-max-intset-entries': '512', - 'zset-max-ziplist-entries': '128', - 'zset-max-ziplist-value': '64', 'hll-sparse-max-bytes': '3000', 'hz': '10', + 'unixsocket': '/var/run/redislite/redis.socket', + 'unixsocketperm': '700', + 'zset-max-ziplist-entries': '128', + 'zset-max-ziplist-value': '64', } @@ -107,7 +107,7 @@ def config_line(setting, value): """ if setting in ['dbfilename', 'dbdir']: if ' ' in value and '"' not in value: - value = '"' + value + '"' + value = '"' + str(value) + '"' return '{setting} {value}'.format(setting=setting, value=value) diff --git a/tests/test_client.py b/tests/test_client.py index 3753f0e..3c23f0c 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -293,9 +293,45 @@ def test_shutdown_race_condition(self): db._cleanup() del db db = redislite.StrictRedis('bug.redis') + db._cleanup() if os.path.exists('bug.redis'): os.remove('bug.redis') + def test_redis_log_attribute(self): + r = redislite.StrictRedis() + self.assertIn('Server started, Redis version', r.redis_log) + + def test_redis_log_tail(self): + r = redislite.StrictRedis() + lines = r.redis_log_tail(2) + self.assertIsInstance(lines, list) + self.assertEqual(len(lines), 2) + + def test_redis_log_many_lines(self): + r = redislite.StrictRedis() + lines = r.redis_log_tail(lines=99999) + self.assertIsInstance(lines, list) + + def test_redis_log_small_chunks(self): + r = redislite.StrictRedis() + lines = r.redis_log_tail(4, width=20) + self.assertIsInstance(lines, list) + self.assertEqual(len(lines), 4) + + def test_redis_log_tail_no_log(self): + r = redislite.StrictRedis() + if os.path.exists(r.logfile): + os.remove(r.logfile) + lines = r.redis_log_tail() + self.assertEqual(lines, []) + + def test_redis_log_tail_empty_log(self): + r = redislite.StrictRedis() + with open(r.logfile, 'w'): + pass + lines = r.redis_log_tail() + self.assertEqual(lines, []) + if __name__ == '__main__': logging.basicConfig(level=logging.DEBUG) diff --git a/tests/test_patch.py b/tests/test_patch.py index a180324..a537fbc 100644 --- a/tests/test_patch.py +++ b/tests/test_patch.py @@ -9,10 +9,13 @@ import inspect import logging import os +import shutil +import tempfile +import unittest import psutil +import redis import redislite import redislite.patch -import unittest logger = logging.getLogger(__name__) @@ -52,6 +55,7 @@ def _log_redis_pid(self, connection): ) def setUp(self): + self.tempdir = tempfile.mkdtemp() logger.info( 'Start Child processes: %d', self._redis_server_processes() ) @@ -60,10 +64,12 @@ def tearDown(self): logger.info( 'End Child processes: %d', self._redis_server_processes() ) + if os.path.exists(self.tempdir) and 'tmp' in self.tempdir: + shutil.rmtree(self.tempdir) + self.tempdir = None def test_redislite_patch_redis_Redis(self): redislite.patch.patch_redis_Redis() - import redis r = redis.Redis() self._log_redis_pid(r) self.assertIsInstance(r.pid, int) # Should have a redislite pid @@ -71,7 +77,6 @@ def test_redislite_patch_redis_Redis(self): def test_redislite_patch_redis_StrictRedis(self): redislite.patch.patch_redis_StrictRedis() - import redis r = redis.StrictRedis() self._log_redis_pid(r) self.assertIsInstance(r.pid, int) # Should have a redislite pid @@ -80,7 +85,6 @@ def test_redislite_patch_redis_StrictRedis(self): # noinspection PyUnusedLocal def test_redislite_patch_redis(self): redislite.patch.patch_redis() - import redis r = redis.Redis() self._log_redis_pid(r) self.assertIsInstance(r.pid, int) # Should have a redislite pid @@ -90,7 +94,6 @@ def test_redislite_patch_redis(self): redislite.patch.unpatch_redis() def test_redislite_double_patch_redis(self): - import redis original_redis = redis.Redis redislite.patch.patch_redis() self.assertNotEqual(original_redis, redis.Redis) @@ -100,11 +103,13 @@ def test_redislite_double_patch_redis(self): self.assertEqual(original_redis, redis.Redis) def test_redislite_patch_redis_with_dbfile(self): - dbfilename = '/tmp/test_redislite_patch_redis_with_dbfile.db' + dbfilename = os.path.join( + self.tempdir, + 'test_redislite_patch_redis_with_dbfile.db' + ) if os.path.exists(dbfilename): os.remove(dbfilename) redislite.patch.patch_redis(dbfilename) - import redis r = redis.Redis() self._log_redis_pid(r) self.assertIsInstance(r.pid, int) # Should have a redislite pid @@ -116,12 +121,40 @@ def test_redislite_patch_redis_with_dbfile(self): self.assertEqual(r.pid, s.pid) redislite.patch.unpatch_redis() + r._cleanup() + s._cleanup() + if os.path.exists(dbfilename): + os.remove(dbfilename) + + def test_redislite_patch_redis_with_dbfile_in_cwd(self): + dbfilename = 'test_redislite_patch_redis_with_dbfile_in_cwd.db' + if os.path.exists(dbfilename): + os.remove(dbfilename) + redislite.patch.patch_redis(dbfilename) + r = redis.Redis() + self._log_redis_pid(r) + self.assertIsInstance(r.pid, int) # Should have a redislite pid + s = redis.Redis() + self._log_redis_pid(s) + self.assertIsInstance(r.pid, int) # Should have a redislite pid + + # Both instances should be talking to the same redis server + self.assertEqual(r.pid, s.pid) + redislite.patch.unpatch_redis() + + r._cleanup() + s._cleanup() + if os.path.exists(dbfilename): + os.remove(dbfilename) + def test_redislite_patch_strictredis_with_dbfile(self): - dbfilename = 'test_redislite_patch_redis_with_short_dbfile.db' + dbfilename = os.path.join( + self.tempdir, + 'test_redislite_patch_redis_with_short_dbfile.db' + ) if os.path.exists(dbfilename): os.remove(dbfilename) redislite.patch.patch_redis_StrictRedis(dbfilename) - import redis r = redis.StrictRedis() self._log_redis_pid(r) self.assertIsInstance(r.pid, int) # Should have a redislite pid diff --git a/tests/test_slave.py b/tests/test_slave.py index 79d8aa0..1cee61e 100644 --- a/tests/test_slave.py +++ b/tests/test_slave.py @@ -8,27 +8,18 @@ Tests for `redislite` module. """ from __future__ import print_function -import logging -import os import time -import redis import redislite -import redislite.patch -import shutil -import stat -import tempfile import unittest -import subprocess # noinspection PyPep8Naming class TestRedisliteSlave(unittest.TestCase): def test_slave(self): - self.master = redislite.Redis(serverconfig={'port': '7000'}) - self.master.set('key', 'value') + master = redislite.Redis(serverconfig={'port': '7000'}) + slave = redislite.Redis(serverconfig={'slaveof': 'localhost 7000'}) + master.set('key', 'value') time.sleep(.5) - s = redislite.Redis(serverconfig={'slaveof': 'localhost 7000'}) - value = s.get('key').decode(encoding='UTF-8') + value = slave.get('key').decode(encoding='UTF-8') self.assertEquals(value, 'value') - From 71263c1046f9bbc3eff9e61e5163c70b83599ae0 Mon Sep 17 00:00:00 2001 From: Dwight Hubbard Date: Thu, 5 May 2016 12:51:44 -0700 Subject: [PATCH 3/4] Deal with dbfilenames that have spaces in them. Add redis-server logging in all cases where the redis server fails to start. Add a new redis_log_tail method to allow tailing the redis server log file and add a redis_log attribute that returns the redis server log as a string. Fix test coverage issues. Code inspection cleanups in client.py --- redislite/client.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/redislite/client.py b/redislite/client.py index 38504e4..c462928 100644 --- a/redislite/client.py +++ b/redislite/client.py @@ -282,6 +282,7 @@ def _load_setting_registry(self): logger.debug('loading settings, found: %s', settings) pidfile = settings.get('pidfile', '') if os.path.exists(pidfile): + # noinspection PyUnusedLocal pid_number = 0 with open(pidfile) as fh: pid_number = int(fh.read()) @@ -289,7 +290,7 @@ def _load_setting_registry(self): process = psutil.Process(pid_number) if not process.is_running(): # pragma: no cover logger.warn( - 'Loaded registry for non-existant redis-server' + 'Loaded registry for non-existent redis-server' ) return else: # pragma: no cover @@ -328,6 +329,7 @@ def __init__(self, *args, **kwargs): # If the user is specifying settings we can't configure just pass the # request to the redis.Redis module if 'host' in kwargs.keys() or 'port' in kwargs.keys(): + # noinspection PyArgumentList super(RedisMixin, self).__init__( *args, **kwargs ) # pragma: no cover @@ -386,6 +388,7 @@ def __init__(self, *args, **kwargs): kwargs['unix_socket_path'] = self.socket_file # noinspection PyArgumentList logger.debug('Calling binding with %s, %s', args, kwargs) + # noinspection PyArgumentList super(RedisMixin, self).__init__(*args, **kwargs) # pragma: no cover logger.debug("Pinging the server to ensure we're connected") @@ -483,6 +486,8 @@ def pid(self): return int(pid) return 0 # pragma: no cover + +# noinspection PyUnresolvedReferences class Redis(RedisMixin, redis.Redis): """ This class provides an enhanced version of the :class:`redis.Redis()` class @@ -568,14 +573,21 @@ class are supported. Attributes ---------- - db : string + + db : str The fully qualified filename associated with the redis dbfilename configuration setting. This attribute is read only. + logfile : str + The name of the redis-server logfile + pid :int Pid of the running embedded redis server, this attribute is read only. + redis_log : str + The contents of the redis-server log file + start_timeout : float Number of seconds to wait for the redis-server process to start before generating a RedisLiteServerStartError exception. @@ -583,6 +595,7 @@ class are supported. pass +# noinspection PyUnresolvedReferences class StrictRedis(RedisMixin, redis.StrictRedis): """ This class provides an enhanced version of the :class:`redis.StrictRedis()` From ba0b9fff5a8f0a87a9dff7b3cfda76bb633b1329 Mon Sep 17 00:00:00 2001 From: Dwight Hubbard Date: Thu, 5 May 2016 15:32:27 -0700 Subject: [PATCH 4/4] Use repr to escape characters --- README.rst | 13 +------------ redislite/client.py | 8 ++++---- redislite/configuration.py | 27 ++++++++++++++------------- tests/test_configuration.py | 14 +++++++------- 4 files changed, 26 insertions(+), 36 deletions(-) diff --git a/README.rst b/README.rst index a324c77..67d30a9 100644 --- a/README.rst +++ b/README.rst @@ -70,24 +70,13 @@ Installing on Mac OSX Redislite for OSX comes as a wheel package by default that can be installed using current versions of pip. -To install Redislite on MacOSX using the sdist package instead you may need +To install Redislite on MacOSX using the sdist package instead you will need the XCode command line utilities installed. If you do not have xcode installed on recent OSX releases they can be installed by running:: xcode-select --install -Note redislite and its dependencies use the gcc compiler. On OSX you may run -into errors indicating that your machine is using clang to compile instead, for -example:: - - clang: error: unknown argument: '-mno-fused-madd' [-Wunused-command-line-argument-hard-error-in-future] - -If this is the case, set your environment variable to override the use of clang -in favor of gcc:: - - CC=gcc - Installation ============ diff --git a/redislite/client.py b/redislite/client.py index c462928..4a6b792 100644 --- a/redislite/client.py +++ b/redislite/client.py @@ -363,9 +363,9 @@ def __init__(self, *args, **kwargs): self.dbfilename = os.path.basename(db_filename) self.dbdir = os.path.dirname(db_filename) - self.settingregistryfile = os.path.join( + self.settingregistryfile = repr(os.path.join( self.dbdir, self.dbfilename + '.settings' - ) + )).strip("'") logger.debug('Setting up redis with rdb file: %s', self.dbfilename) logger.debug('Setting up redis with socket file: %s', self.socket_file) @@ -380,9 +380,9 @@ def __init__(self, *args, **kwargs): if not self.dbdir: self.dbdir = self.redis_dir - self.settingregistryfile = os.path.join( + self.settingregistryfile = repr(os.path.join( self.dbdir, self.dbfilename + '.settings' - ) + )).strip("'") self._start_redis() kwargs['unix_socket_path'] = self.socket_file diff --git a/redislite/configuration.py b/redislite/configuration.py index 6e00b19..f041553 100644 --- a/redislite/configuration.py +++ b/redislite/configuration.py @@ -16,7 +16,7 @@ 'activerehashing': 'yes', 'aof-rewrite-incremental-fsync': 'yes', 'appendonly': 'no', - 'appendfilename': '"appendonly.aof"', + 'appendfilename': 'appendonly.aof', 'appendfsync': 'everysec', 'aof-load-truncated': 'yes', 'auto-aof-rewrite-percentage': '100', @@ -26,34 +26,34 @@ 'databases': '16', 'dbdir': './', 'dbfilename': 'redis.db', + 'hash-max-ziplist-entries': '512', + 'hash-max-ziplist-value': '64', + 'hll-sparse-max-bytes': '3000', + 'hz': '10', + 'list-max-ziplist-entries': '512', + 'list-max-ziplist-value': '64', 'loglevel': 'notice', 'logfile' : 'redis.log', + 'lua-time-limit': '5000', 'pidfile': '/var/run/redislite/redis.pid', 'port': '0', 'save': ['900 1', '300 100', '60 200', '15 1000'], + 'stop-writes-on-bgsave-error': 'yes', 'tcp-backlog': '511', 'tcp-keepalive': '0', - 'stop-writes-on-bgsave-error': 'yes', 'rdbcompression': 'yes', 'rdbchecksum': 'yes', - 'timeout': '0', 'slave-serve-stale-data': 'yes', 'slave-read-only': 'yes', 'repl-disable-tcp-nodelay': 'no', 'slave-priority': '100', 'no-appendfsync-on-rewrite': 'no', - 'lua-time-limit': '5000', 'slowlog-log-slower-than': '10000', 'slowlog-max-len': '128', 'latency-monitor-threshold': '0', 'notify-keyspace-events': '""', - 'hash-max-ziplist-entries': '512', - 'hash-max-ziplist-value': '64', - 'list-max-ziplist-entries': '512', - 'list-max-ziplist-value': '64', 'set-max-intset-entries': '512', - 'hll-sparse-max-bytes': '3000', - 'hz': '10', + 'timeout': '0', 'unixsocket': '/var/run/redislite/redis.socket', 'unixsocketperm': '700', 'zset-max-ziplist-entries': '128', @@ -105,9 +105,10 @@ def config_line(setting, value): str The configuration line based on the setting and value """ - if setting in ['dbfilename', 'dbdir']: - if ' ' in value and '"' not in value: - value = '"' + str(value) + '"' + if setting in [ + 'appendfilename', 'dbfilename', 'dbdir', 'dir', 'pidfile', 'unixsocket' + ]: + value = repr(value) return '{setting} {value}'.format(setting=setting, value=value) diff --git a/tests/test_configuration.py b/tests/test_configuration.py index 6a7fb4b..26b1708 100644 --- a/tests/test_configuration.py +++ b/tests/test_configuration.py @@ -78,7 +78,7 @@ def test_configuration_config_line(self): result = redislite.configuration.config_line( 'dbfilename', 'test file.db' ) - self.assertEqual('dbfilename "test file.db"', result) + self.assertEqual("dbfilename 'test file.db'", result) def test_configuration_config(self): result = redislite.configuration.config() @@ -123,12 +123,12 @@ def test_configuration_config_db(self): ) self.assertIn('\ndaemonize yes', result) - self.assertIn('\npidfile ' + pidfile, result) - self.assertIn('\ndbfilename test.db', result) + self.assertIn('\npidfile ' + repr(pidfile), result) + self.assertIn("\ndbfilename 'test.db'", result) def test_configuration_config_db_with_space(self): - pidfile = os.path.join(self.tempdir, 'test.pid') - unixsocket = os.path.join(self.tempdir, 'redis.socket') + pidfile = os.path.join(self.tempdir, 'test space.pid') + unixsocket = os.path.join(self.tempdir, 'test space.socket') result = redislite.configuration.config( pidfile=pidfile, unixsocket=unixsocket, @@ -137,8 +137,8 @@ def test_configuration_config_db_with_space(self): ) self.assertIn('\ndaemonize yes', result) - self.assertIn('\npidfile ' + pidfile, result) - self.assertIn('\ndbfilename "test space.db"', result) + self.assertIn('\npidfile ' + repr(pidfile), result) + self.assertIn("\ndbfilename 'test space.db'", result) def test_configuration_config_slave(self): result = redislite.configuration.config(