PK!K`SSeeve/__init__.py"""eeve - A flexible, powerfull and simple event trigger""" __version__ = '0.2.0' __author__ = 'Victor Marcelino ' __all__ = [] import travel_backpack import os import eeve.helpers as helpers from eeve.importer import import_from_folder from eeve.wrapper import action_wrapper from eeve.action import Action import eeve.mappings as mappings all_triggers, all_actions = {}, {} def main(): script_root = os.path.dirname(os.path.realpath(__file__)) load_triggers(os.path.join(script_root, 'eeve triggers')) load_actions(os.path.join(script_root, 'eeve actions')) load_triggers(os.path.join(script_root, 'eeve plugins')) load_actions(os.path.join(script_root, 'eeve plugins')) load_events(os.path.join(script_root, 'eeve events.txt')) def load_triggers(path): modules = import_from_folder(path) for module in modules: try: triggers = getattr(module, 'triggers', None) for trigger_name, trigger in triggers.items(): print('loading', trigger_name) all_triggers[trigger_name] = trigger except Exception as ex: print('invalid action module:', ex) print('--all triggers loaded--') def load_actions(path): modules = import_from_folder(path) for module in modules: try: actions = getattr(module, 'actions', None) for action_name, action in actions.items(): print('loading', action_name) all_actions[action_name] = action except Exception as ex: print('invalid action module:', ex) print('--all actions loaded--') def load_events(path): with open(path) as f: all_events = f.read().split('\n') for event in all_events: if event and not event.startswith('#'): show_traceback = False print(f'loading [{event}]') if event.startswith('[test]'): show_traceback = True event = event[len('[test]'):] try: event = mappings.remap(event) trigger, raw_actions = helpers.strip_split(event, mappings.char_map['->'], maxsplit=1) trigger, trigger_args, trigger_kwargs = helpers.process_args(trigger, return_init_args=False) raw_actions = helpers.strip_split(raw_actions, mappings.char_map[';']) actions = [] for action in raw_actions: action_name, action_init_args, action_init_kwargs, action_run_args, action_run_kwargs = helpers.process_args( action, return_init_args=True) _action = all_actions[action_name] action_init_result = None action_run = None action_task_info_getter = None if type(_action) is dict: if 'class' in _action: action_init_result = _action['class'](*action_init_args, **action_init_kwargs) action_run = action_init_result.run else: if 'init' in _action: action_init_result = _action['init'](*action_init_args, **action_init_kwargs) action_run = _action['run'] action_task_info_getter = _action.get('task_info', None) else: action_init_result = _action(*action_init_args, **action_init_kwargs) action_run = action_init_result.run #print(action_run) action_run = travel_backpack.except_and_print(action_run) act = Action( func=action_run, run_args=action_run_args, run_kwargs=action_run_kwargs, init_result=action_init_result, task_info_getter=action_task_info_getter, name=action_name) actions.append(act) #action_run = action_wrapper(action_run, action_run_args, action_run_kwargs, debug=show_traceback) task = action_wrapper(actions, debug=show_traceback) all_triggers[trigger](task, *trigger_args, **trigger_kwargs) except Exception as ex: print('invalid event:', (ex if not show_traceback else travel_backpack.format_exception_string(ex))) print('--all events loaded--')PK!feeve/__main__.pyfrom eeve import main main()PK!?2eeve/action.pyfrom dataclasses import dataclass from typing import Union, Any, Callable @dataclass class Action: func: Callable name: str run_args: Union[list, tuple] run_kwargs: dict init_result: Any = None task_info_getter: Callable = None def update_task_info(self, task_info): if self.task_info_getter is not None: self.task_info_getter(self.init_result, task_info)PK!uE..$eeve/eeve actions/changePowerPlan.pyimport subprocess import sys mappings = None def get_power_plan_info(print_to_screen=True): global mappings proc = subprocess.Popen(["powercfg", "/l"], stdout=subprocess.PIPE, shell=True) (out, err) = proc.communicate() result = str(out, 'utf-8').replace('\r', '').split('\n')[3:][:-1] result = [r.split(' ', 4)[3:] for r in result] mappings = {} active_plan = None for i in range(len(result)): temp_result = result[i][1].split('(', 1)[1:][0].split(')') result[i][1] = temp_result[0] mappings[result[i][1]] = result[i][0] if temp_result[1].replace(' ', '') == '*': active_plan = temp_result[0] if print_to_screen: print(">>", result[i]) return mappings, active_plan def set_power_plan(power_plan_name): if mappings is None: get_power_plan_info(print_to_screen=False) proc = subprocess.Popen(["powercfg", "/s", mappings[power_plan_name]], stdout=subprocess.PIPE, shell=True) (out, err) = proc.communicate() result2 = str(out, 'utf-8').replace('\r', '') #print(result2) if __name__ == '__main__': _, active_plan = get_power_plan_info() print("Currently active:", active_plan) plan = input("power mode: ") if len(sys.argv) < 2 else sys.argv[1] set_power_plan(plan) _, active_plan = get_power_plan_info(print_to_screen=False) print("Set active:", active_plan) class SetPowerPlan: def run(self, plan_name): _, active_plan = get_power_plan_info(print_to_screen=False) print("Last power plan:", active_plan) set_power_plan(plan_name) _, active_plan = get_power_plan_info(print_to_screen=False) print("Current power plan:", active_plan) actions = {'set power plan': SetPowerPlan} PK!d6!eeve/eeve actions/REST_request.pyimport requests import time class Request: def run(self, method, url, *args, retry_count=-1, wait_time=5, **kwargs): retry = True while retry: try: print('REST request:', method, url, args, kwargs) requests.request(method, url) retry = False except requests.exceptions.ConnectionError as e: print(e) if retry_count == 0: retry = False else: retry_count -= 1 time.sleep(wait_time) retry = True actions = {'rest request': Request}PK!"eeve/eeve actions/start_process.pyimport subprocess def run(*args, windowed=False, **kwargs): if windowed: kwargs['creationflags'] = subprocess.CREATE_NEW_CONSOLE print('start process:', args, kwargs) subprocess.Popen(args, **kwargs) actions = {'start process': {'run': run}} PK!' v*OO eeve/eeve actions/test_action.pyfrom eeve.variable import Variable def init(*args, **kwargs): print('initialization args:', args, kwargs) def run(*args, index=0, **kwargs): index_is_var = hasattr(index, 'value') idx = index.value if index_is_var else index print(f'run args ({idx}):', args, kwargs, end=' ') try: if index_is_var: index.value += 1 else: index += 1 except Exception as e: print(e, end='') index = 1 print() return {'index': index} actions = {'test action': {'init': init, 'run': run}} PK!|uu eeve/eeve actions/wait_action.pyfrom time import sleep from eeve.taskinfo import TaskInfo class IfAction: def run(self, parameter, end=False, inverse=False): if not end: if not ((not parameter) if inverse else parameter): if_count = 1 for i, action in self.info.get_next_actions(): if action.name == 'end if': if_count -= 1 elif action.name == 'if': if_count += 1 if if_count == 0: self.info.current_action_index = i break else: # if didn't hit break statement self.info.current_action_index = len(self.info.actions) self.info.increment_action_index = False def set_task_info(self, info: TaskInfo): self.info = info actions = { 'wait': { 'run': sleep }, 'if': { 'class': IfAction, 'task_info': IfAction.set_task_info }, 'end if': { 'run': lambda: IfAction().run(parameter=None, end=True) } } PK!CReeve/eeve events.txt#[test]timer: 2 -> test action: init param 1, init param 2, init_par1=True, init_par2=False, init_par3= teste teste | trigger_result=$return_result, run param 1, run param2, run_par1=True, run_par2=False, run_par3= teste teste #[test]timer: 5, start=true -> test action: trigger_result=$return_result, index=$index; test action: trigger_result=$return_result, index=$index; test action: trigger_result=$return_result, index=$index #timer: 5, start=true -> test action: locals=$vars, protected=$$vars, public=$$$vars, index=$index; test action: locals=$vars, protected=$$vars, public=$$$vars, index=$index; test action: locals=$vars, protected=$$vars, public=$$$vars, index=$index; test action: locals=$vars, protected=$$vars, public=$$$vars, index=$index; test action: locals=$vars, protected=$$vars, public=$$$vars, index=$index display: off -> set power plan: Power saver display: on -> start process: cmd, /C, echo oi&&pause, windowed=True display: on -> set power plan: Balanced display: on -> rest request: GET, http\://192.168.10.11\:2280/surveillance/stop, wait_time=1 session end -> rest request: GET, http\://192.168.10.11\:2280/surveillance/start system suspend -> rest request: GET, http\://192.168.10.11\:2280/surveillance/start TP-Link device: connect -> if:$is_on; set TP-Link device property: device=$device, is_on=False; wait: 0.5; set TP-Link device property: device=$device, is_on=True; end ifPK!=uu!eeve/eeve plugins/tp-interface.pyfrom pyHS100 import Discover import travel_backpack import time class SmartDeviceContainer: def __init__(self, dev): self.device = dev self.hw_id = self.device.hw_info['hwId'] self.alias = self.device.alias self.disconnect_count = 0 def __hash__(self): h = hash(self.hw_id) #print('hash:', h) return h def __eq__(self, other): return self.hw_id == other.hw_id def __repr__(self): alias = self.alias + ' (offline)' try: alias = self.device.alias except: pass return alias class Discoverer(metaclass=travel_backpack.Singleton): def __init__(self): print('inited') self.timeout = 1 self.time_between_pings = 0 self.single_connect_event = [] self.single_disconnect_event = [] self.multi_connect_event = [] self.multi_disconnect_event = [] self.discoverer_thread = self.discoverer() def set_params(self, timeout, time_between_pings, threshold): self.timeout = timeout self.time_between_pings = time_between_pings self.threshold = threshold @travel_backpack.threadpool def discoverer(self): current_device_set = set() while True: #print('\nloop start') new_device_set = set() for ip, dev in Discover.discover(timeout=self.timeout).items(): try: dev = SmartDeviceContainer(dev) new_device_set.add(dev) except: pass offline_devices = current_device_set - new_device_set #print('offline devices:'.ljust(18), (offline_devices) or '-') for dev in offline_devices: if dev.disconnect_count > self.threshold: print(dev, 'disconnected') for e in self.single_disconnect_event: e(device=dev.device) else: dev.disconnect_count += 1 print(dev.alias, 'hwid:', dev.hw_id, 'id:', id(dev), 'dcnts:', dev.disconnect_count) new_device_set.add(dev) offline_devices = current_device_set - new_device_set for e in self.multi_disconnect_event: e(device_list=[d.device for d in offline_devices]) new_devices = new_device_set - current_device_set #print('new_devices:'.ljust(18), (new_devices) or '-') for e in self.multi_connect_event: e(device_list=[d.device for d in new_devices]) for dev in new_devices: print(dev, 'connected') for e in self.single_connect_event: e(device=dev.device, is_on=dev.device.is_on) #print('noch:'.ljust(18), (new_device_set & current_device_set) or '-') current_device_set = new_device_set time.sleep(self.time_between_pings) def register_trigger(action, trigger_status, mult='single', timeout=1, time_between_pings=2, threshold=3): d = Discoverer() if trigger_status == 'connect': if mult == 'single': d.single_connect_event.append(action) elif mult == 'multi': d.multi_connect_event.append(action) elif trigger_status == 'disconnect': if mult == 'single': d.single_disconnect_event.append(action) elif mult == 'multi': d.multi_disconnect_event.append(action) d.set_params(timeout=timeout, time_between_pings=time_between_pings, threshold=threshold) def set_device_property(device, brightness=None, temperature=None, is_on=None): if brightness is not None: device.brightness = brightness if temperature is not None: device.color_temp = temperature if is_on is not None: if is_on: device.turn_on() else: device.turn_off() actions = {'set TP-Link device property': {'run': set_device_property}} triggers = {'TP-Link device': register_trigger} if __name__ == "__main__": def a(*args, **kwargs): print('==>', *args, **kwargs) def b(*args, **kwargs): print('<==', *args, **kwargs) register_trigger(a, 'connect') register_trigger(b, 'disconnect') PK!T66&eeve/eeve triggers/broadcastCatcher.pyfrom travel_backpack import log_info import win32con import win32api import win32gui import time from ctypes import POINTER, windll, Structure, cast, CFUNCTYPE, c_int, c_uint, c_void_p, c_bool from comtypes import GUID from ctypes.wintypes import HANDLE, DWORD from datetime import datetime as dt now = dt.now h_log_info = log_info log_info = lambda info: h_log_info(info, file='System.log') PBT_POWERSETTINGCHANGE = 0x8013 display_on_callbacks = [] display_off_callbacks = [] display_dim_callbacks = [] session_end_callbacks = [] sys_suspend_callbacks = [] def display_change(data): mapping = {0: 'off', 1: 'on', 2: 'dimmed'} status = mapping[data] if status == 'on': for c in display_on_callbacks: print('fon') c() elif status == 'off': for c in display_off_callbacks: print('foff') c() elif status == 'dimmed': for c in display_dim_callbacks: print('fdim') c() return "Display " + status power_settings = { 'SYSTEM_AWAYMODE': { 'GUID': '{98A7F580-01F7-48AA-9C0F-44352C29E5C0}', 'Data': { 0: 'Exiting away mode', 1: 'Entering away mode' } }, 'CONSOLE_DISPLAY_STATE': { 'GUID': '{6FE69556-704A-47A0-8F24-C28D936FDA47}', 'Data': display_change }, 'ACDC_POWER_SOURCE': { 'GUID': '{5D3E9A59-E9D5-4B00-A6BD-FF34FF516548}', 'Data': { 0: 'AC power', 1: 'DC power (batteries)', 2: 'Short term power source (UPS)' } }, 'BATTERY_PERCENTAGE_REMAINING': { 'GUID': '{A7AD8041-B45A-4CAE-87A3-EECBB468A9E1}', 'Data': lambda batt: f'Battery remaining: {batt}' } } GUID_to_name = {v['GUID']: k for k, v in power_settings.items()} def process_power_broadcast(lparam): settings = cast(lparam, POINTER(POWERBROADCAST_SETTING)).contents power_setting_GUID = str(settings.PowerSetting) data_length = settings.DataLength data = settings.Data data_info = power_settings.get(GUID_to_name.get(power_setting_GUID)).get('Data') if data_info is None: log_info(f'Power setting changed but GUID is unknown: {power_setting_GUID}') elif callable(data_info): log_info(data_info(data)) else: log_info(data_info.get(data, f'Unknown Data: {hex(data)}({data})')) def system_suspend(x): for c in sys_suspend_callbacks: print('fssus') c() log_info('System suspend') power_broadcast_wParams = { win32con.PBT_APMPOWERSTATUSCHANGE: lambda x: log_info('Power status has changed'), win32con.PBT_APMRESUMEAUTOMATIC: lambda x: log_info('System resume'), win32con.PBT_APMRESUMESUSPEND: lambda x: log_info('System resume by user input'), win32con.PBT_APMSUSPEND: system_suspend, PBT_POWERSETTINGCHANGE: process_power_broadcast } end_session_lParams = { 0x00000000: 'Shutdown or Restart', 0x00000001: 'Using file that must be replaced, system being serviced or resourses exausted', 0x40000000: 'Force shutdown', 0x80000000: 'User logging off' } class POWERBROADCAST_SETTING(Structure): _fields_ = [("PowerSetting", GUID), ("DataLength", DWORD), ("Data", DWORD)] def wndproc(hwnd, msg, wparam, lparam): if msg == win32con.WM_POWERBROADCAST: power_broadcast_wParams.get(wparam, lambda x: log_info(f'Unknown wParam for WM_POWERBROADCAST ({wparam})'))(lparam) return True elif msg == win32con.WM_QUERYENDSESSION: for c in session_end_callbacks: print('fsend') c() for k, v in end_session_lParams.items(): if lparam & k: log_info(v) #return False # to cancel shutdown return True elif msg == win32con.WM_ENDSESSION: for k, v in end_session_lParams.items(): if lparam & k: log_info(v) return 0 else: log_info(f"wndproc: {msg}\nw: {hex(wparam)}\nl: {hex(lparam)}") running = False def run(): global running if running: return running = True log_info("*** STARTING ***") running = True hinst = win32api.GetModuleHandle(None) wndclass = win32gui.WNDCLASS() wndclass.hInstance = hinst wndclass.lpszClassName = "testWindowClass" CMPFUNC = CFUNCTYPE(c_bool, c_int, c_uint, c_uint, c_void_p) wndproc_pointer = CMPFUNC(wndproc) messageMap = { win32con.WM_POWERBROADCAST: wndproc_pointer, win32con.WM_QUERYENDSESSION: wndproc, win32con.WM_ENDSESSION: wndproc, win32con.WM_SYSCOMMAND: wndproc, win32con.WM_DESTROY: wndproc, win32con.WM_CLOSE: wndproc, win32con.WM_QUIT: wndproc } wndclass.lpfnWndProc = messageMap try: myWindowClass = win32gui.RegisterClass(wndclass) hwnd = win32gui.CreateWindowEx(win32con.WS_EX_LEFT, myWindowClass, "testMsgWindow", 0, 0, 0, win32con.CW_USEDEFAULT, win32con.CW_USEDEFAULT, 0, 0, hinst, None) except Exception as e: log_info("Exception: %s" % str(e)) if hwnd is None: log_info("hwnd is none!") else: log_info("hwnd: %s" % hwnd) register_function = windll.user32.RegisterPowerSettingNotification hwnd_pointer = HANDLE(hwnd) for name, power_setting_info in power_settings.items(): result = register_function(hwnd_pointer, GUID(power_setting_info['GUID']), DWORD(0)) print('registering', name) #print('result:', hex(result)) #print('lastError:', win32api.GetLastError()) #print() print('\nEntering loop') while True: win32gui.PumpWaitingMessages() time.sleep(1) #print('.', end='', flush=True) if __name__ == "__main__": run() def thread_run(): import travel_backpack travel_backpack.threadpool(run)() return global running if not running: running = True import travel_backpack travel_backpack.threadpool(run)() class DisplayOff: def __init__(self, action, status): #print(action) if status == 'on': display_on_callbacks.append(action) elif status == 'off': display_off_callbacks.append(action) elif status == 'dimmed': display_dim_callbacks.append(action) thread_run() class SessionEnd: def __init__(self, action): session_end_callbacks.append(action) thread_run() class SystemSuspend: def __init__(self, action): sys_suspend_callbacks.append(action) thread_run() triggers = {'display': DisplayOff, 'session end': SessionEnd, 'system suspend': SystemSuspend} PK!<#eeve/eeve triggers/timer_trigger.py_DEFAULT_POOL = None def threadpool(f, executor=None): global _DEFAULT_POOL from functools import wraps import concurrent.futures if _DEFAULT_POOL is None: _DEFAULT_POOL = concurrent.futures.ThreadPoolExecutor() @wraps(f) def wrap(*args, **kwargs): return (executor or _DEFAULT_POOL).submit(f, *args, **kwargs) return wrap class TimerTrigger: def __init__(self, action, t, *args, start=False, **kwargs): self.args = args self.action = action self.start = start #print('Loadinnnnnnn') self.run(int(t)) #print('loadeded') def unregister(self): self.callback = None @threadpool def run(self, t): import time if self.start: self.action(time=t) while True: time.sleep(t) print('triggering action') self.action(time=t) triggers = {'timer': TimerTrigger}PK!>> eeve/eeve.pyif __name__ == "__main__": from . import main main()PK!Eeeve/helpers.pydef strip_split(s, *args, **kwargs): return list(map(lambda x: x.strip(), s.split(*args, **kwargs))) def try_cast(tp, obj): try: tp(obj) return True except: return False def get_true_value(x): if try_cast(int, x): return int(x) elif try_cast(float, x): return float(x) elif x.lower() == 'true': return True elif x.lower() == 'false': return False else: return x def split_args(arg_string, return_args, return_kwargs): args = strip_split(arg_string, mappings.char_map[',']) for arg in args: if mappings.char_map['='] in arg: k, v = strip_split(arg, mappings.char_map['='], maxsplit=1) return_kwargs[k] = get_true_value(v) else: return_args.append(get_true_value(arg)) import eeve.mappings as mappings def process_args(command_string, return_init_args): init_args, run_args = [], [] init_kwargs, run_kwargs = {}, {} if mappings.char_map[':'] in command_string: command_name, temp_args = strip_split(command_string, mappings.char_map[':'], maxsplit=1) arg_split = strip_split(temp_args, mappings.char_map['|'], maxsplit=1) if len(arg_split) == 1: temp_init_args = None temp_run_args = arg_split[0] else: temp_init_args, temp_run_args = arg_split if temp_init_args: split_args(temp_init_args, init_args, init_kwargs) split_args(temp_run_args, run_args, run_kwargs) else: command_name = command_string if return_init_args: return command_name, init_args, init_kwargs, run_args, run_kwargs else: return command_name, run_args, run_kwargsPK!'eeve/importer.pyimport os import sys import importlib def import_from_folder(folder): imported_files = [] folder = os.path.abspath(folder) if folder not in sys.path: sys.path.insert(0, folder) for file_obj in os.listdir(folder): print('inspecting', file_obj) file_obj = os.path.join(folder, file_obj) if os.path.isfile(file_obj): if file_obj.endswith('.py'): module_name = os.path.splitext(os.path.basename(file_obj))[0] print('==> importing', module_name) imported_files.append(importlib.import_module(module_name)) elif os.path.isdir(file_obj): if os.path.basename(file_obj) not in ['.', '..', '__pycache__']: module_name = os.path.basename(file_obj) print('--> importing', module_name) imported_files.append(importlib.import_module(module_name)) return imported_files PK!$7eeve/mappings.py#import uuid import re #u = lambda: str(uuid.uuid4()).replace('-', '') special_chars = [':', '->', '=', ',', ';', '|'] weird_chars = 'ᨀᨁᨂᨃᨄᨅᨆᨇᨈ' char_map = {c: weird_chars[i] for i, c in enumerate(special_chars)} slash = 'Ø' def remap(e): e = replace_slashes(e) for char in char_map: #print('searching ', char) def sub(pat): #print('found:', '[', pat[0], ']') return pat[0][0] + char_map[char] c = char.replace('|', r'\|').replace('$', r'\$') pattern = fr"[^({slash})]{c}" e = re.sub(pattern, sub, e) #print(e) #print() return e.replace(slash, '') def replace_slashes(s): replaces = [] mx = len(s) i = 0 while i < mx: if s[i] == '\\': replaces.append(i) i += 1 i += 1 for r in reversed(replaces): s = s[:r] + slash + s[r + 1:] return s # test if __name__ == '__main__': char_map = {k: f'<[{k}]>' for k in char_map} slash = '#' s = r'timer: 2 -> test action: oi\, tudo bem? \=\,\\ Eu \= vc , init_par3= teste teste | trigger_result=$return_result' replaces = [] mx = len(s) i = 0 while i < mx: if s[i] == '\\': replaces.append(i) i += 1 i += 1 for r in reversed(replaces): s = s[:r] + slash + s[r + 1:] print(s) s = remap(s).replace(slash, '') print(s) print('end')PK!(/eeve/taskinfo.pyfrom eeve.variable import VariableGroup from eeve.action import Action from dataclasses import dataclass from typing import List @dataclass class TaskInfo: actions: List[Action] global_variables: VariableGroup task_variables: VariableGroup local_variables: VariableGroup current_action_index: int = 0 increment_action_index: bool = True def get_next_actions(self): return enumerate(self.actions[self.current_action_index:], self.current_action_index)PK!dIIeeve/variable.pyclass Variable: def __init__(self, name: str, value): self.value = value self._name = name @property def name(self): return self._name class VariableGroup: def __init__(self): self.vars = dict() def __getitem__(self, key): return self.vars[key].value def __setitem__(self, key, value): if type(value) is Variable: self.vars[key] = value else: self.vars[key] = Variable(name=key, value=value) def update(self, new: dict): for k, v in new.items(): self.__setitem__(key=k, value=v) def get(self, var, default=None): if var in self.vars: return self[var] else: return default def get_var(self, var): if var not in self.vars: self.vars[var] = Variable(name=var, value=None) return self.vars[var] def to_kwargs(self) -> dict: result = dict() for k, v in self.vars.items(): result[k] = v.value return resultPK!eeve/wrapper.pyfrom functools import wraps from copy import deepcopy from eeve.action import Action from eeve.variable import VariableGroup from eeve.taskinfo import TaskInfo from typing import List import travel_backpack global_variables = VariableGroup() def action_wrapper(actions: List[Action], debug=False): task_variables = VariableGroup() def start_task(**kwargs): local_variables = VariableGroup() task_info = TaskInfo(actions=actions, global_variables=global_variables, task_variables=task_variables, local_variables=local_variables) local_variables.update(kwargs) while task_info.current_action_index < len(task_info.actions): action = task_info.actions[task_info.current_action_index] _run_args = deepcopy(action.run_args) _run_kwargs = deepcopy(action.run_kwargs) if debug: print('------------------------------------------------------------processing act', action) for i, arg in enumerate(_run_args): if type(arg) is str: if debug: print('------------------------------------------------------------processing arg', arg) if arg.startswith('var$'): arg = arg[3:] # remove var prefix if arg.startswith('$$$'): if arg == '$$$vars': _run_args[i] = global_variables.vars else: _run_args[i] = global_variables.get_var(arg[3:]) elif arg.startswith('$$'): if arg == '$$vars': _run_args[i] = task_variables.vars else: _run_args[i] = task_variables.get_var(arg[2:]) elif arg.startswith('$'): if arg == '$vars': _run_args[i] = local_variables.vars else: _run_args[i] = local_variables.get_var(arg[1:]) else: if arg.startswith('$$$'): if arg == '$$$vars': _run_args[i] = global_variables.to_kwargs() else: _run_args[i] = global_variables.get(arg[3:], arg) elif arg.startswith('$$'): if arg == '$$vars': _run_args[i] = task_variables.to_kwargs() else: _run_args[i] = task_variables.get(arg[2:], arg) elif arg.startswith('$'): if arg == '$vars': _run_args[i] = local_variables.to_kwargs() else: _run_args[i] = local_variables.get(arg[1:], arg) for k, v in _run_kwargs.items(): if type(v) is str: #if v.startswith('$'): # if v == '$return_result': # _run_kwargs[k] = local_variables # else: # _run_kwargs[k] = local_variables.get(v[1:], v) if debug: print('------------------------------------------------------------processing kwarg', v) if v.startswith('var$'): v = v[3:] # remove var prefix if v.startswith('$$$'): if v == '$$$vars': _run_kwargs[k] = global_variables.vars else: _run_kwargs[k] = global_variables.get_var(v[3:]) elif v.startswith('$$'): if v == '$$vars': _run_kwargs[k] = task_variables.vars else: _run_kwargs[k] = task_variables.get_var(v[2:]) elif v.startswith('$'): if v == '$vars': _run_kwargs[k] = local_variables.vars else: _run_kwargs[k] = local_variables.get_var(v[1:]) else: if v.startswith('$$$'): if v == '$$$vars': _run_kwargs[k] = global_variables.to_kwargs() else: _run_kwargs[k] = global_variables.get(v[3:], v) elif v.startswith('$$'): if v == '$$vars': _run_kwargs[k] = task_variables.to_kwargs() else: _run_kwargs[k] = task_variables.get(v[2:], v) elif v.startswith('$'): if v == '$vars': _run_kwargs[k] = local_variables.to_kwargs() else: _run_kwargs[k] = local_variables.get(v[1:], v) if debug: print('call args:', _run_args, _run_kwargs) action.update_task_info(task_info) run_result = action.func(*_run_args, **_run_kwargs) if type(run_result) is dict: local_variables.update(run_result) if task_info.increment_action_index: task_info.current_action_index += 1 return travel_backpack.except_and_print(start_task) PK!:U&-&-eeve-0.2.0.dist-info/LICENSE Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. PK!HڽTUeeve-0.2.0.dist-info/WHEEL A н#Z;/"d&F[xzw@Zpy3Fv]\fi4WZ^EgM_-]#0(q7PK!HFvQeeve-0.2.0.dist-info/METADATASn0 +x܀YZ`5X݊q0Q$٩~&kʓM| %Ig"3jKuLܵxCO\z(lZcP7kl!p0k Yʼ6%<9mRUݍn\>^sEMK-ee.Ur} #؍ah;n9Pn{LsF&gƢowKu^mNzN} ZnjMv"_ >' QAwdRW2#_Թ+U`Dl$e'zJSbEP :d[e2w*v5Xt)1Ccʅz4c6{$.?*ߌN29G\,lq&Q8! `Hcɷ7x^pY/ Lp1UtX YNGN=N~ ~)?PK!HţNeeve-0.2.0.dist-info/RECORDunX}?E?$6^`0yo{o#{OuNI2%79nA@4:UCh驖eϩ81d>zn.TP |Cu7  t  tfgH1ƋI6 xED0o¦ApgT]rG!ӜKywVDa!RgM fmjԏ4߸cJڶ{\vKA-}ۢsWGJ3q$\OcpJ磅b㻩-fC wC%s/΂F3[sUԠNlҖKLټsT?=ߩfA:jN<W6!49߸-aE>upj(> ^eeve/eeve.pyPK!E_eeve/helpers.pyPK!'Nfeeve/importer.pyPK!$7Cjeeve/mappings.pyPK!(/mpeeve/taskinfo.pyPK!dIIreeve/variable.pyPK! weeve/wrapper.pyPK!:U&-&-eeve-0.2.0.dist-info/LICENSEPK!HڽTUteeve-0.2.0.dist-info/WHEELPK!HFvQeeve-0.2.0.dist-info/METADATAPK!HţN*eeve-0.2.0.dist-info/RECORDPKM