Extract `Job.get_call_string` logic to `utils.get_call_string` (#1499)

* Extract `Job.get_call_string` logic to `utils.get_call_string`

* Remove an outdaded comment

* Move `truncate_long_string` to `utils`

* Remove `truncate` parameter in `get_call_string`

* Add a test for `get_call_string`

* Move `truncate_long_string` to module's top level

* Add a test case for `truncate_long_string` suite
main
Adrian Sadłocha 4 years ago committed by GitHub
parent 5590aab458
commit caa4efc35b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -22,7 +22,7 @@ from .exceptions import DeserializationError, NoSuchJobError
from .local import LocalStack
from .serializers import resolve_serializer
from .utils import (get_version, import_attribute, parse_timeout, str_to_date,
utcformat, utcnow, ensure_list)
utcformat, utcnow, ensure_list, get_call_string)
# Serialize pickle dumps using the highest pickle protocol (binary, default
# uses ascii)
@ -45,12 +45,6 @@ class JobStatus(str, Enum):
UNEVALUATED = object()
def truncate_long_string(data, maxlen=75):
""" Truncates strings longer than maxlen
"""
return (data[:maxlen] + '...') if len(data) > maxlen else data
def cancel_job(job_id, connection=None):
"""Cancels the job with the given job ID, preventing execution. Discards
any job info (i.e. it can't be requeued later).
@ -801,17 +795,7 @@ class Job:
"""Returns a string representation of the call, formatted as a regular
Python function invocation statement.
"""
if self.func_name is None:
return None
arg_list = [as_text(truncate_long_string(repr(arg))) for arg in self.args]
kwargs = ['{0}={1}'.format(k, as_text(truncate_long_string(repr(v)))) for k, v in self.kwargs.items()]
# Sort here because python 3.3 & 3.4 makes different call_string
arg_list += sorted(kwargs)
args = ', '.join(arg_list)
return '{0}({1})'.format(self.func_name, args)
return get_call_string(self.func_name, self.args, self.kwargs, max_length=75)
def cleanup(self, ttl=None, pipeline=None, remove_from_queue=True):
"""Prepare job for eventual deletion (if needed). This method is usually

@ -297,3 +297,27 @@ def split_list(a_list, segment_size):
"""
for i in range(0, len(a_list), segment_size):
yield a_list[i:i + segment_size]
def truncate_long_string(data, max_length=None):
"""Truncate arguments with representation longer than max_length"""
if max_length is None:
return data
return (data[:max_length] + '...') if len(data) > max_length else data
def get_call_string(func_name, args, kwargs, max_length=None):
"""Returns a string representation of the call, formatted as a regular
Python function invocation statement. If max_length is not None, truncate
arguments with representation longer than max_length.
"""
if func_name is None:
return None
arg_list = [as_text(truncate_long_string(repr(arg), max_length)) for arg in args]
kwargs = ['{0}={1}'.format(k, as_text(truncate_long_string(repr(v), max_length))) for k, v in kwargs.items()]
arg_list += sorted(kwargs)
args = ', '.join(arg_list)
return '{0}({1})'.format(func_name, args)

@ -11,7 +11,7 @@ from redis import Redis
from tests import RQTestCase, fixtures
from rq.utils import backend_class, ensure_list, first, get_version, is_nonstring_iterable, parse_timeout, utcparse, \
split_list, ceildiv
split_list, ceildiv, get_call_string, truncate_long_string
from rq.exceptions import TimeoutFormatError
@ -113,3 +113,26 @@ class TestUtils(RQTestCase):
expected_small_list_count = ceildiv(BIG_LIST_SIZE, SEGMENT_SIZE)
self.assertEqual(len(small_lists), expected_small_list_count)
def test_truncate_long_string(self):
"""Ensure truncate_long_string works properly"""
assert truncate_long_string("12", max_length=3) == "12"
assert truncate_long_string("123", max_length=3) == "123"
assert truncate_long_string("1234", max_length=3) == "123..."
assert truncate_long_string("12345", max_length=3) == "123..."
s = "long string but no max_length provided so no truncating should occur" * 10
assert truncate_long_string(s) == s
def test_get_call_string(self):
"""Ensure a case, when func_name, args and kwargs are not None, works properly"""
cs = get_call_string("f", ('some', 'args', 42), {"key1": "value1", "key2": True})
assert cs == "f('some', 'args', 42, key1='value1', key2=True)"
def test_get_call_string_with_max_length(self):
"""Ensure get_call_string works properly when max_length is provided"""
func_name = "f"
args = (1234, 12345, 123456)
kwargs = {"len4": 1234, "len5": 12345, "len6": 123456}
cs = get_call_string(func_name, args, kwargs, max_length=5)
assert cs == "f(1234, 12345, 12345..., len4=1234, len5=12345, len6=12345...)"

Loading…
Cancel
Save