#170: Implemented cartesian product and other sub-item rules
This commit is contained in:
+237
-17
@@ -53,6 +53,212 @@ class AppBase:
|
|||||||
if ret.status_code != 200:
|
if ret.status_code != 200:
|
||||||
self.logger.info(ret.text)
|
self.logger.info(ret.text)
|
||||||
|
|
||||||
|
async def cartesian_product(self, L):
|
||||||
|
if L:
|
||||||
|
return {(a, ) + b for a in L[0] for b in await self.cartesian_product(L[1:])}
|
||||||
|
else:
|
||||||
|
return {()}
|
||||||
|
|
||||||
|
# Returns a list of all the executions to be done in the inner loop
|
||||||
|
# FIXME: Doesn't take into account whether you actually WANT to loop or not
|
||||||
|
# Check if the last part of the value is #?
|
||||||
|
async def get_param_multipliers(self, baseparams):
|
||||||
|
# Example:
|
||||||
|
# {'call': ['hello', 'hello4'], 'call2': ['hello2', 'hello3'], 'call3': '1'}
|
||||||
|
#
|
||||||
|
# Should become this because of pairs (all same-length arrays, PROBABLY indicates same source node's values.
|
||||||
|
# [
|
||||||
|
# {'call': 'hello', 'call2': 'hello2', 'call3': '1'},
|
||||||
|
# {'call': 'hello4', 'call2': 'hello3', 'call3': '1'}
|
||||||
|
# ]
|
||||||
|
#
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
|
# Example2:
|
||||||
|
# {'call': ['hello'], 'call2': ['hello2', 'hello3'], 'call3': '1'}
|
||||||
|
#
|
||||||
|
# Should become this because NOT pairs/triplets:
|
||||||
|
# [
|
||||||
|
# {'call': 'hello', 'call2': 'hello2', 'call3': '1'},
|
||||||
|
# {'call': 'hello', 'call2': 'hello3', 'call3': '1'}
|
||||||
|
# ]
|
||||||
|
#
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
|
# Example3:
|
||||||
|
# {'call': ['hello', 'hello2'], 'call2': ['hello3', 'hello4', 'hello5'], 'call3': '1'}
|
||||||
|
#
|
||||||
|
# Should become this because arrays are not same length, aka no pairs/triplets. This is the multiplier effect. 2x3 arrays = 6 iterations
|
||||||
|
# [
|
||||||
|
# {'call': 'hello', 'call2': 'hello3', 'call3': '1'},
|
||||||
|
# {'call': 'hello', 'call2': 'hello4', 'call3': '1'},
|
||||||
|
# {'call': 'hello', 'call2': 'hello5', 'call3': '1'},
|
||||||
|
# {'call': 'hello2', 'call2': 'hello3', 'call3': '1'},
|
||||||
|
# {'call': 'hello2', 'call2': 'hello4', 'call3': '1'},
|
||||||
|
# {'call': 'hello2', 'call2': 'hello5', 'call3': '1'}
|
||||||
|
# ]
|
||||||
|
# To achieve this, we'll do this:
|
||||||
|
# 1. For the first array, take the total amount(y) (2x3=6) and divide it by the current array (x): 2. x/y = 3. This means do 3 of each value
|
||||||
|
# 2. For the second array, take the total amount(y) (2x3=6) and divide it by the current array (x): 3. x/y = 2.
|
||||||
|
# 3. What does the 3rd array do? Same, but ehhh?
|
||||||
|
|
||||||
|
paramlist = []
|
||||||
|
listitems = []
|
||||||
|
listlengths = []
|
||||||
|
all_lists = []
|
||||||
|
all_list_keys = []
|
||||||
|
for key, value in baseparams.items():
|
||||||
|
if isinstance(value, list):
|
||||||
|
if len(value) <= 1:
|
||||||
|
if len(value) == 1:
|
||||||
|
baseparams[key] = value[0]
|
||||||
|
|
||||||
|
else:
|
||||||
|
if len(value) not in listlengths:
|
||||||
|
listlengths.append(len(value))
|
||||||
|
|
||||||
|
listitems.append(
|
||||||
|
{
|
||||||
|
key: len(value)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
all_list_keys.append(key)
|
||||||
|
all_lists.append(baseparams[key])
|
||||||
|
else:
|
||||||
|
print("%s is not a list: " % value)
|
||||||
|
|
||||||
|
print("Listlengths: %s" % listlengths)
|
||||||
|
if len(listlengths) <= 1:
|
||||||
|
print("NO MULTIPLIER NECESSARY. Length is %d" % len(listitems))
|
||||||
|
for item in listitems:
|
||||||
|
# This loops should always be length 1
|
||||||
|
for key, value in item.items():
|
||||||
|
if isinstance(value, int):
|
||||||
|
print("\nShould run key %s %d times from %s" % (key, value, baseparams[key]))
|
||||||
|
if len(paramlist) == value:
|
||||||
|
print("List ALREADY exists - just changing values")
|
||||||
|
for subloop in range(value):
|
||||||
|
baseitem = copy.deepcopy(baseparams)
|
||||||
|
paramlist[subloop][key] = baseparams[key][subloop]
|
||||||
|
else:
|
||||||
|
print("List DOESNT exist - ADDING values")
|
||||||
|
for subloop in range(value):
|
||||||
|
baseitem = copy.deepcopy(baseparams)
|
||||||
|
baseitem[key] = baseparams[key][subloop]
|
||||||
|
paramlist.append(baseitem)
|
||||||
|
|
||||||
|
else:
|
||||||
|
print("Multipliers to handle: %s" % listitems)
|
||||||
|
newlength = 1
|
||||||
|
for item in listitems:
|
||||||
|
for key, value in item.items():
|
||||||
|
newlength = newlength * value
|
||||||
|
|
||||||
|
print("Newlength of array: %d. Lists: %s" % (newlength, all_lists))
|
||||||
|
# Get the cartesian product of the arrays
|
||||||
|
cartesian = await self.cartesian_product(all_lists)
|
||||||
|
newlist = []
|
||||||
|
for item in cartesian:
|
||||||
|
newlist.append(list(item))
|
||||||
|
|
||||||
|
newobject = {}
|
||||||
|
for subitem in range(len(newlist)):
|
||||||
|
baseitem = copy.deepcopy(baseparams)
|
||||||
|
for key in range(len(newlist[subitem])):
|
||||||
|
baseitem[all_list_keys[key]] = newlist[subitem][key]
|
||||||
|
|
||||||
|
paramlist.append(baseitem)
|
||||||
|
|
||||||
|
print("PARAMLIST: %s" % paramlist)
|
||||||
|
|
||||||
|
|
||||||
|
#newlist[subitem[0]]
|
||||||
|
|
||||||
|
#if len(newlist) > 0:
|
||||||
|
# itemlength = len(newlist[0])
|
||||||
|
|
||||||
|
# How do we get it back, ordered?
|
||||||
|
#for item in cartesian:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#print("Listlengths: %s" % listlengths)
|
||||||
|
#paramlist = [baseparams]
|
||||||
|
|
||||||
|
print("Return paramlist: %s" % paramlist)
|
||||||
|
return paramlist
|
||||||
|
|
||||||
|
|
||||||
|
# Runs recursed versions with inner loops and such
|
||||||
|
async def run_recursed_items(self, func, baseparams, loop_wrapper):
|
||||||
|
has_loop = False
|
||||||
|
|
||||||
|
newparams = {}
|
||||||
|
for key, value in baseparams.items():
|
||||||
|
if isinstance(value, list) and len(value) == 1 and isinstance(value[0], list):
|
||||||
|
try:
|
||||||
|
loop_wrapper[key] += 1
|
||||||
|
except IndexError:
|
||||||
|
loop_wrapper[key] = 1
|
||||||
|
except KeyError:
|
||||||
|
loop_wrapper[key] = 1
|
||||||
|
|
||||||
|
print("Key %s is a list: %s" % (key, value))
|
||||||
|
newparams[key] = value[0]
|
||||||
|
has_loop = True
|
||||||
|
else:
|
||||||
|
print("Key %s is NOT a list within a list: %s" % (key, value))
|
||||||
|
newparams[key] = value
|
||||||
|
|
||||||
|
results = []
|
||||||
|
if has_loop:
|
||||||
|
print("Should run inner loop: %s" % newparams)
|
||||||
|
ret = await self.run_recursed_items(func, newparams, loop_wrapper)
|
||||||
|
|
||||||
|
else:
|
||||||
|
print("Should run with params (inner): %s" % newparams)
|
||||||
|
|
||||||
|
# 1. Find the loops that are required and create new multipliers
|
||||||
|
# If here: check for multipliers within this scope.
|
||||||
|
ret = []
|
||||||
|
param_multiplier = await self.get_param_multipliers(newparams)
|
||||||
|
print("Multiplier length: %d" % len(param_multiplier))
|
||||||
|
for subparams in param_multiplier:
|
||||||
|
ret.append(await func(**subparams))
|
||||||
|
|
||||||
|
print("Ret length: %d" % len(ret))
|
||||||
|
|
||||||
|
if len(ret) == 1:
|
||||||
|
ret = ret[0]
|
||||||
|
|
||||||
|
print("Return from execution: %s" % ret)
|
||||||
|
if ret == None:
|
||||||
|
results.append("")
|
||||||
|
json_object = False
|
||||||
|
elif isinstance(ret, dict):
|
||||||
|
results.append(ret)
|
||||||
|
json_object = True
|
||||||
|
elif isinstance(ret, list):
|
||||||
|
results.append(ret)
|
||||||
|
json_object = True
|
||||||
|
else:
|
||||||
|
ret = ret.replace("\"", "\\\"", -1)
|
||||||
|
|
||||||
|
try:
|
||||||
|
results.append(json.loads(ret))
|
||||||
|
json_object = True
|
||||||
|
except json.decoder.JSONDecodeError as e:
|
||||||
|
#print("Json: %s" % e)
|
||||||
|
results.append(ret)
|
||||||
|
|
||||||
|
if len(results) == 1:
|
||||||
|
results = results[0]
|
||||||
|
|
||||||
|
print("\nLOOP: %s\nRESULTS: %s" % (loop_wrapper, results))
|
||||||
|
return results
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Things to consider for files:
|
# Things to consider for files:
|
||||||
# - How can you download / stream a file?
|
# - How can you download / stream a file?
|
||||||
# - Can you decide if you want a stream or the files directly?
|
# - Can you decide if you want a stream or the files directly?
|
||||||
@@ -871,6 +1077,9 @@ class AppBase:
|
|||||||
if sourcevalue.isdigit() and destinationvalue.isdigit():
|
if sourcevalue.isdigit() and destinationvalue.isdigit():
|
||||||
if int(sourcevalue) > int(destinationvalue):
|
if int(sourcevalue) > int(destinationvalue):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
print("Not larger than.")
|
||||||
|
return False
|
||||||
except AttributeError as e:
|
except AttributeError as e:
|
||||||
self.logger.error("Condition larger than failed with values %s and %s: %s" % (sourcevalue, destinationvalue, e))
|
self.logger.error("Condition larger than failed with values %s and %s: %s" % (sourcevalue, destinationvalue, e))
|
||||||
return False
|
return False
|
||||||
@@ -879,6 +1088,9 @@ class AppBase:
|
|||||||
if sourcevalue.isdigit() and destinationvalue.isdigit():
|
if sourcevalue.isdigit() and destinationvalue.isdigit():
|
||||||
if int(sourcevalue) < int(destinationvalue):
|
if int(sourcevalue) < int(destinationvalue):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
print("Not small than.")
|
||||||
|
return False
|
||||||
except AttributeError as e:
|
except AttributeError as e:
|
||||||
self.logger.error("Condition smaller than failed with values %s and %s: %s" % (sourcevalue, destinationvalue, e))
|
self.logger.error("Condition smaller than failed with values %s and %s: %s" % (sourcevalue, destinationvalue, e))
|
||||||
return False
|
return False
|
||||||
@@ -1426,23 +1638,30 @@ class AppBase:
|
|||||||
|
|
||||||
print("4")
|
print("4")
|
||||||
print("Running with params (1): %s" % baseparams)
|
print("Running with params (1): %s" % baseparams)
|
||||||
ret = await func(**baseparams)
|
|
||||||
print("Return from execution: %s" % ret)
|
|
||||||
if ret == None:
|
|
||||||
results.append("")
|
|
||||||
json_object = False
|
|
||||||
elif isinstance(ret, dict) or isinstance(ret, list):
|
|
||||||
results.append(ret)
|
|
||||||
json_object = True
|
|
||||||
else:
|
|
||||||
ret = ret.replace("\"", "\\\"", -1)
|
|
||||||
|
|
||||||
try:
|
results = await self.run_recursed_items(func, baseparams, {})
|
||||||
results.append(json.loads(ret))
|
if isinstance(results, dict) or isinstance(results, list):
|
||||||
json_object = True
|
json_object = True
|
||||||
except json.decoder.JSONDecodeError as e:
|
|
||||||
#print("Json: %s" % e)
|
# Check the structure here. If "isloop", try to recurse?
|
||||||
results.append(ret)
|
# ret, is_loop = recurse_json(innervalue, parsersplit[outercnt+1:])
|
||||||
|
#ret = await func(**baseparams)
|
||||||
|
#print("Return from execution: %s" % ret)
|
||||||
|
#if ret == None:
|
||||||
|
# results.append("")
|
||||||
|
# json_object = False
|
||||||
|
#elif isinstance(ret, dict) or isinstance(ret, list):
|
||||||
|
# results.append(ret)
|
||||||
|
# json_object = True
|
||||||
|
#else:
|
||||||
|
# ret = ret.replace("\"", "\\\"", -1)
|
||||||
|
|
||||||
|
# try:
|
||||||
|
# results.append(json.loads(ret))
|
||||||
|
# json_object = True
|
||||||
|
# except json.decoder.JSONDecodeError as e:
|
||||||
|
# #print("Json: %s" % e)
|
||||||
|
# results.append(ret)
|
||||||
|
|
||||||
#print("Inner ret parsed: %s" % ret)
|
#print("Inner ret parsed: %s" % ret)
|
||||||
|
|
||||||
@@ -1460,6 +1679,7 @@ class AppBase:
|
|||||||
result += item
|
result += item
|
||||||
except json.decoder.JSONDecodeError as e:
|
except json.decoder.JSONDecodeError as e:
|
||||||
# Common nested issue which puts " around everything
|
# Common nested issue which puts " around everything
|
||||||
|
print("Decodingerror: %s" % e)
|
||||||
try:
|
try:
|
||||||
tmpitem = item.replace("\\\"", "\"", -1)
|
tmpitem = item.replace("\\\"", "\"", -1)
|
||||||
json.loads(tmpitem)
|
json.loads(tmpitem)
|
||||||
@@ -1473,7 +1693,7 @@ class AppBase:
|
|||||||
result = result[:-2]
|
result = result[:-2]
|
||||||
result += "]"
|
result += "]"
|
||||||
else:
|
else:
|
||||||
print("Normal result?")
|
print("Normal result - no list?")
|
||||||
result = results
|
result = results
|
||||||
|
|
||||||
print("RESULT: %s" % result)
|
print("RESULT: %s" % result)
|
||||||
|
|||||||
Reference in New Issue
Block a user