python - How can I remove need for these checking functions to be global -
i using python test rest api. response message json , want check each field. have created check_json function , check against checker dictionary. checker dictionary has string key name of key in json value tuple (a pair) first bool parameter, whether item mandatory , second parameter either object direct compare or function add more involved checking functionality.
i make check this:
r= check_json(myjson, checker)
where r result in format: 'field': true or false - dependent on whether check passed or failed
the code little messay lots of global functions. 1 idea include checking functions in check_json. have been told use closures. how?
here code:
# check nested json import json import collections import functools import datetime #this json session myjson = { "accessed": "wed, 31 jul 2013 13:03:38 gmt", "created": "wed, 31 jul 2013 13:03:38 gmt", "dnurls": [ "http://135.86.180.69:8580/ucc/api/v1/session/dns/50000" ], "expires": "wed, 31 jul 2013 13:03:48 gmt", "modified": "wed, 31 jul 2013 13:03:38 gmt", "name": "kw50000", "person": { "employeeid": "kw50000", "firstname": "kw50000", "lastname": "dev5" }, "previewredirect": { "destination": "", "enabled": false, "setupenabled": false } } def isdate(s): try: testdate = datetime.datetime.strptime(s, '%a, %d %b %y %h:%m:%s gmt') return true except exception: print "conversion date failed" return false def isurl(l): count = 0 item in l: count += 1 if item.startswith("http://") else (-1) return count > 0 def isalnum(s): return s.isalnum() def isbool(s): return type(s) == bool def isany(s): return true #checker object made of dictionary string key , tuple value (a pair) #tuple first filed flag indicating whether key mandatory or not. # tuple 2nd key value expect or checker function checker = { "accessed": (true, isdate), "created": (true, isdate), "dnurls": (true, isurl), "expires": (true, isdate), "modified": (true, isdate), "name": (true, "kw50000"), "person": (true, { "employeeid": (true, isalnum), "firstname": (false, isany), "lastname": (false, isany) }), "previewredirect": (true, { "destination": (false, isany), "enabled": (true, isbool), "setupenabled": (false, isbool) }) } # returns dictionary key= fieldname, value = result, either true (test pass), false (test failed) def check_json(obj, checker): """params json check, template comparison object returns dictionary of keys pass/fail values""" result = {} k, (mflag, chk) in checker.iteritems(): if not k in obj: result[k] = not mflag elif isinstance(chk, collections.callable): result[k] = chk(obj[k]) elif(isinstance(chk, collections.mapping)): result[k] = check_json(obj[k], chk) else: result[k] = chk == obj[k] return result def with_and(v1, v2): return functools.reduce(with_and, v2.itervalues(), v1) if isinstance(v2, collections.mapping) else v1 , v2 r= check_json(myjson, checker) print "r={}".format(r) isok = functools.reduce(with_and, r.itervalues(), true) print "result {}: {}".format(isok, r)
here possible approach. have decide whether more readable/maintainable/etc.
# check nested json import collections functools import reduce import datetime #this json session myjson = { "accessed": "wed, 31 jul 2013 13:03:38 gmt", "created": "wed, 31 jul 2013 13:03:38 gmt", "dnurls": [ "http://135.86.180.69:8580/ucc/api/v1/session/dns/50000" ], "expires": "wed, 31 jul 2013 13:03:48 gmt", "modified": "wed, 31 jul 2013 13:03:38 gmt", "name": "kw50000", "person": { "employeeid": "kw50000", "firstname": "kw50000", "lastname": "dev5" }, "previewredirect": { "destination": "", "enabled": false, "setupenabled": false } } # returns dictionary key= fieldname, value = result, # either true (test pass), false (test failed) def check_json(obj, checker): """params json check, template comparison object returns dictionary of keys pass/fail values""" result = {} k, (mflag, chk) in checker.items(): if not k in obj: result[k] = not mflag elif isinstance(chk, collections.callable): result[k] = chk(obj[k]) elif(isinstance(chk, collections.mapping)): result[k] = check_json(obj[k], chk) else: result[k] = chk == obj[k] return result def isdate(s): try: datetime.datetime.strptime(s, '%a, %d %b %y %h:%m:%s gmt') return true except exception: print("conversion date failed") return false #checker object made of dictionary string key , tuple value (a pair) #tuple first filed flag indicating whether key mandatory or not. # tuple 2nd key value expect or checker function checker = { "accessed": (true, check_json.isdate), "created": (true, check_json.isdate), "dnurls": (true, lambda l: (reduce(lambda c, v:\ c + (1 if v.startswith('http://') else -1), l, 0) > 0)), "expires": (true, check_json.isdate), "modified": (true, check_json.isdate), "name": (true, "kw50000"), "person": (true, { "employeeid": (true, lambda s: s.isalnum()), "firstname": (false, true), "lastname": (false, true) }), "previewredirect": (true, { "destination": (false, true), "enabled": (true, lambda s: type(s) bool), "setupenabled": (false, lambda s: type(s) bool) }) } def with_and(v1, v2): return functools.reduce(with_and, v2.values(), v1)\ if isinstance(v2, collections.mapping) else v1 , v2 r = check_json(myjson, checker) print("r={}".format(r)) isok = functools.reduce(with_and, r.values(), true) print("result {}: {}".format(isok, r))
note code has been modified python3. main change use lambdas
wherever possible, , use nested functions otherwise eliminate global name-space dependencies.
Comments
Post a Comment