datetime compatibility option for callbacks
This commit is contained in:
parent
658953af54
commit
842754c2d3
2 changed files with 65 additions and 1 deletions
|
|
@ -25,6 +25,7 @@ import logging
|
|||
import sys
|
||||
import traceback
|
||||
import six
|
||||
from koji.util import encode_datetime_recurse
|
||||
|
||||
# the available callback hooks and a list
|
||||
# of functions to be called for each event
|
||||
|
|
@ -165,6 +166,13 @@ def ignore_error(f):
|
|||
setattr(f, 'failure_is_an_option', True)
|
||||
return f
|
||||
|
||||
|
||||
def convert_datetime(f):
|
||||
"""Indicate that callback needs to receive datetime objects as strings"""
|
||||
setattr(f, 'convert_datetime', True)
|
||||
return f
|
||||
|
||||
|
||||
def register_callback(cbtype, func):
|
||||
if not cbtype in callbacks:
|
||||
raise koji.PluginError('"%s" is not a valid callback type' % cbtype)
|
||||
|
|
@ -172,12 +180,15 @@ def register_callback(cbtype, func):
|
|||
raise koji.PluginError('%s is not callable' % getattr(func, '__name__', 'function'))
|
||||
callbacks[cbtype].append(func)
|
||||
|
||||
|
||||
def run_callbacks(cbtype, *args, **kws):
|
||||
if not cbtype in callbacks:
|
||||
raise koji.PluginError('"%s" is not a valid callback type' % cbtype)
|
||||
cache = {}
|
||||
for func in callbacks[cbtype]:
|
||||
cb_args, cb_kwargs = _fix_cb_args(func, args, kws, cache)
|
||||
try:
|
||||
func(cbtype, *args, **kws)
|
||||
func(cbtype, *cb_args, **cb_kwargs)
|
||||
except:
|
||||
msg = 'Error running %s callback from %s' % (cbtype, func.__module__)
|
||||
if getattr(func, 'failure_is_an_option', False):
|
||||
|
|
@ -185,3 +196,10 @@ def run_callbacks(cbtype, *args, **kws):
|
|||
else:
|
||||
tb = ''.join(traceback.format_exception(*sys.exc_info()))
|
||||
raise koji.CallbackError('%s:\n%s' % (msg, tb))
|
||||
|
||||
|
||||
def _fix_cb_args(func, args, kwargs, cache):
|
||||
if getattr(func, 'convert_datetime', False):
|
||||
args = encode_datetime_recurse(args)
|
||||
kwargs = encode_datetime_recurse(kwargs)
|
||||
return args, kwargs
|
||||
|
|
|
|||
46
koji/util.py
46
koji/util.py
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
from __future__ import absolute_import
|
||||
import calendar
|
||||
import datetime
|
||||
from fnmatch import fnmatch
|
||||
import koji
|
||||
import logging
|
||||
|
|
@ -151,6 +152,51 @@ def dslice_ex(dict, keys, strict=True):
|
|||
del ret[key]
|
||||
return ret
|
||||
|
||||
|
||||
class DataWalker(object):
|
||||
|
||||
def __init__(self, data, callback, kwargs=None):
|
||||
self.data = data
|
||||
self.callback = callback
|
||||
if kwargs is None:
|
||||
kwargs = {}
|
||||
self.kwargs = kwargs
|
||||
|
||||
def walk(self):
|
||||
return self._walk(self.data)
|
||||
|
||||
def _walk(self, value):
|
||||
# first let callback filter the value
|
||||
value = self.callback(value, **self.kwargs)
|
||||
# then recurse if needed
|
||||
if isinstance(value, tuple):
|
||||
return tuple([self._walk(x) for x in value])
|
||||
elif isinstance(value, list):
|
||||
return list([self._walk(x) for x in value])
|
||||
elif isinstance(value, dict):
|
||||
ret = {}
|
||||
for k in value:
|
||||
k = self._walk(k)
|
||||
v = self._walk(value[k])
|
||||
ret[k] = v
|
||||
return ret
|
||||
else:
|
||||
return value
|
||||
|
||||
|
||||
def encode_datetime(value):
|
||||
"""Convert datetime objects to strings"""
|
||||
if isinstance(value, datetime.datetime):
|
||||
return value.isoformat(' ')
|
||||
else:
|
||||
return value
|
||||
|
||||
|
||||
def encode_datetime_recurse(value):
|
||||
walker = DataWalker(value, encode_datetime)
|
||||
return walker.walk()
|
||||
|
||||
|
||||
def call_with_argcheck(func, args, kwargs=None):
|
||||
"""Call function, raising ParameterError if args do not match"""
|
||||
if kwargs is None:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue