Files
Sub-Zero.bundle/Contents/Code/interface/func.py
T
2018-09-07 22:56:01 +02:00

186 lines
6.4 KiB
Python

# coding=utf-8
import datetime
import operator
from support.config import config
from support.helpers import timestamp
def enable_channel_wrapper(func, enforce_route=False):
"""
returns the original wrapper :func: (route or handler) if applicable, else the plain to-be-wrapped function
:param func: original wrapper
:return: original wrapper or wrapped function
"""
def noop(*args, **kwargs):
def inner(*a, **k):
"""
:param a: args
:param k: kwargs
:return: originally to-be-wrapped function
"""
return a[0] if len(a) else a
return inner
def wrap(*args, **kwargs):
return (func if (config.enable_channel or enforce_route) else noop)(*args, **kwargs)
return wrap
ROUTE_REGISTRY = {}
def get_func_name(args):
return list(args).pop(0).__name__
def get_lookup_key(f, args, kwargs):
return tuple([f.__name__, tuple(args), tuple([(key, value) for key, value in kwargs.iteritems()])])
def should_debounce(f, key, kw):
return getattr(f, "debounce", False) and "randomize" in kw and key in Dict["menu_history"]
def register_route_function(f):
fn = f.__name__
if fn != "ValidatePrefs" and fn not in ROUTE_REGISTRY:
ROUTE_REGISTRY[fn] = f
return f
def main_menu_fallback():
key = get_lookup_key(ROUTE_REGISTRY["fatality"], [], {})
Dict["last_menu_item"] = key
add_to_menu_history(key)
return ROUTE_REGISTRY["fatality"](randomize=timestamp())
def add_to_menu_history(key):
# add function to menu history
mh = Dict["menu_history"]
if key in mh:
del mh[key]
mh[key] = datetime.datetime.now() + datetime.timedelta(hours=6)
# limit to 25 items
Dict["menu_history"] = dict(sorted(sorted(mh.items(), key=operator.itemgetter(1),
reverse=True)[:25]))
try:
Dict.Save()
except TypeError:
Log.Error("Can't save menu history for: %r", key)
del Dict["menu_history"][key]
def route_wrapper(*args, **kwargs):
def wrap(f):
already_wrapped = getattr(f, "orig_f", False)
register_route_function(f)
def inner(*a, **kw):
if "menu_history" not in Dict:
Dict["menu_history"] = {}
if "last_menu_item" not in Dict:
Dict["last_menu_item"] = None
key = get_lookup_key(f, list(a), kw)
ret_f = f
ret_a = a
ret_kw = kw
# mh = Dict["menu_history"]
# mh_keys = [k for k, v in sorted(mh.items(), key=operator.itemgetter(1))]
#
# fallback_needed = False
# fallback_found = False
if should_debounce(ret_f, key, kw):
# special case for TriggerRestart
if ret_f.__name__ in ("TriggerRestart", "Restart"):
Log.Debug("Don't trigger a re-restart, falling back to main menu")
else:
Log.Debug("not triggering %s twice with %s, %s, returning to main menu" %
(f.__name__, a, kw))
return main_menu_fallback()
#
# fallback_needed = True
#
# # try to find a suitable fallback route in case we've encountered an already visited
# # debounced route
# fallbacks = []
# current_last_visit = mh[key]
# last_menu_item = Dict["last_menu_item"]
# direction_backwards = True
#
# if last_menu_item and last_menu_item in mh and key in mh:
# last_mi_pos = mh_keys.index(last_menu_item)
# current_mi_pos = mh_keys.index(key)
# if current_mi_pos > -1 and last_mi_pos > -1:
# print "SHEKEL", current_mi_pos, last_mi_pos, current_mi_pos < last_mi_pos
# only consider items in menu history that have an older timestamp than the current
# for key_, last_visit in sorted(mh.items(), key=operator.itemgetter(1),
# reverse=True):
# if last_visit < current_last_visit:
# fallbacks.append(key_)
#
# for key_ in fallbacks:
# # old data structure
# if not len(key_) == 3 or not (isinstance(key_[1], tuple) and isinstance(key_[2], tuple)):
# continue
#
# old_f, old_a, old_kw = key_
# if old_f == "ValidatePrefs":
# continue
#
# possible_fallback = ROUTE_REGISTRY[old_f]
#
# # non-debounced function found
# if not getattr(possible_fallback, "debounce", False):
# ret_kw = dict(old_kw)
# ret_a = old_a
# if "randomize" in ret_kw:
# ret_kw["randomize"] = timestamp()
#
# ret_f = possible_fallback
# key = get_lookup_key(ret_f, list(ret_a), ret_kw)
# fallback_found = True
#
# Log.Debug("not triggering %s twice with %s, %s, returning to %s, %s, %s" %
# (f.__name__, a, kw, ret_f.__name__, ret_a, ret_kw))
#
# break
#
# if not fallback_found:
# Log.Debug("No fallback found in menu history for %s, falling back to main menu", f)
# return main_menu_fallback()
# if not fallback_needed:
# add_to_menu_history(key)
# if ret_f.__name__ != "ValidatePrefs":
# Dict["last_menu_item"] = key
#
add_to_menu_history(key)
Dict["last_menu_item"] = key
return ret_f(*ret_a, **ret_kw)
# @route may be used multiple times
enforce_route = kwargs.pop("enforce_route", None)
if not already_wrapped:
inner.orig_f = f
return enable_channel_wrapper(route(*args, **kwargs), enforce_route=enforce_route)(inner)
return enable_channel_wrapper(route(*args, **kwargs), enforce_route=enforce_route)(f)
return wrap