diff --git a/koji/plugin.py b/koji/plugin.py index 6191f2e2..396b8111 100644 --- a/koji/plugin.py +++ b/koji/plugin.py @@ -200,6 +200,16 @@ def run_callbacks(cbtype, *args, **kws): def _fix_cb_args(func, args, kwargs, cache): if getattr(func, 'convert_datetime', False): - args = encode_datetime_recurse(args) - kwargs = encode_datetime_recurse(kwargs) + if id(args) in cache: + args = cache[id(args)] + else: + val = encode_datetime_recurse(args) + cache[id(args)] = val + args = val + if id(kwargs) in cache: + kwargs = cache[id(kwargs)] + else: + val = encode_datetime_recurse(kwargs) + cache[id(kwargs)] = val + kwargs = val return args, kwargs diff --git a/tests/test_lib/test_plugin.py b/tests/test_lib/test_plugin.py index ea24be33..f064a5d3 100644 --- a/tests/test_lib/test_plugin.py +++ b/tests/test_lib/test_plugin.py @@ -104,6 +104,10 @@ class TestCallbacks(unittest.TestCase): def datetime_callback(self, cbtype, *args, **kwargs): self.callbacks.append([cbtype, args, kwargs]) + @koji.plugin.convert_datetime + def datetime_callback2(self, cbtype, *args, **kwargs): + self.callbacks.append([cbtype, args, kwargs]) + def test_simple_callback(self): args = ('hello',) kwargs = {'world': 1} @@ -146,6 +150,34 @@ class TestCallbacks(unittest.TestCase): self.assertEqual(len(self.callbacks), 1) self.assertEqual(self.callbacks[0], [cbtype, args2, kwargs2]) + def test_multiple_datetime_callback(self): + dt1 = datetime.datetime.now() + dt2 = datetime.datetime(2001,1,1) + args = (dt1,"2",["three"], {4: dt2},) + kwargs = {'foo': [dt1, dt2]} + cbtype = 'preTag' + koji.plugin.register_callback(cbtype, self.datetime_callback) + koji.plugin.register_callback(cbtype, self.datetime_callback2) + koji.plugin.run_callbacks(cbtype, *args, **kwargs) + args2 = koji.util.encode_datetime_recurse(args) + kwargs2 = koji.util.encode_datetime_recurse(kwargs) + self.assertEqual(len(self.callbacks), 2) + self.assertEqual(self.callbacks[0], [cbtype, args2, kwargs2]) + self.assertEqual(self.callbacks[1], [cbtype, args2, kwargs2]) + # verify that caching worked + # unfortunately, args and kwargs get unpacked and repacked, so we have + # to dig down + cb_args1 = self.callbacks[0][1] + cb_args2 = self.callbacks[1][1] + for i in range(len(cb_args1)): + if cb_args1[i] is not cb_args2[i]: + raise Exception("converted args not cached") + cb_kwargs1 = self.callbacks[0][2] + cb_kwargs2 = self.callbacks[1][2] + for k in cb_kwargs1: + if cb_kwargs1[k] is not cb_kwargs2[k]: + raise Exception("converted kwargs not cached") + def test_bad_callback(self): args = ('hello',) kwargs = {'world': 1}