cengal.code_flow_control.chained_flow.versions.v_1.chained_flow
1#!/usr/bin/env python 2# coding=utf-8 3 4# Copyright © 2012-2024 ButenkoMS. All rights reserved. Contacts: <gtalk@butenkoms.space> 5# 6# Licensed under the Apache License, Version 2.0 (the "License"); 7# you may not use this file except in compliance with the License. 8# You may obtain a copy of the License at 9# 10# http://www.apache.org/licenses/LICENSE-2.0 11# 12# Unless required by applicable law or agreed to in writing, software 13# distributed under the License is distributed on an "AS IS" BASIS, 14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15# See the License for the specific language governing permissions and 16# limitations under the License. 17 18import sys 19import os 20import copy 21import traceback 22from enum import Enum 23from contextlib import contextmanager 24from cengal.data_generation.id_generator import IDGenerator, GeneratorType 25from cengal.code_flow_control.smart_values.versions.v_1.smart_values import * 26 27""" 28Module Docstring 29Docstrings: http://www.python.org/dev/peps/pep-0257/ 30""" 31 32__author__ = "ButenkoMS <gtalk@butenkoms.space>" 33__copyright__ = "Copyright © 2012-2024 ButenkoMS. All rights reserved. Contacts: <gtalk@butenkoms.space>" 34__credits__ = ["ButenkoMS <gtalk@butenkoms.space>", ] 35__license__ = "Apache License, Version 2.0" 36__version__ = "4.4.1" 37__maintainer__ = "ButenkoMS <gtalk@butenkoms.space>" 38__email__ = "gtalk@butenkoms.space" 39# __status__ = "Prototype" 40__status__ = "Development" 41# __status__ = "Production" 42 43 44class ChainLinkFailed(Exception): pass 45 46 47class ChainClosed(Exception): 48 """ 49 link considers it ordinary external exception 50 """ 51 52 def __init__(self, chain, link_id, link_info): 53 super(ChainClosed, self).__init__('Content Holder is closed. ' 54 'Content Holder ID: {}; ' 55 'Content Holder Info: {}; ' 56 'Link ID: {}; ' 57 'Link Info {}'.format(str(chain._chain_id), 58 str(chain._chain_info), 59 str(link_id), 60 str(link_info))) 61 self.chain = chain 62 self.link_id = link_id 63 self.link_info = link_info 64 65 66class ChainFunctionParameterNeeded(Exception): pass 67 68 69class CriteriaType(Enum): 70 # class CriteriaType(): # much more efficient than Enum inheritance 71 needed = 0 # only set of this links is needed (should be already successfully done) 72 optional = 1 # all links are needed except of this set of links 73 any = 2 # any result will fit criteria 74 forbidden = 3 # set of this links should be already failed 75 not_successful = 4 # set of this links should not be successfully done (also may not start) at the check time 76 77 78class IgnoreLinkResultCriteriaType(Enum): 79 do_not_ignore = 0 80 ignore_if_failed = 1 81 ignore_if_successful = 2 82 83 84class ChainHistoryExport(Exception): 85 def __init__(self, history, process_error_result=True): 86 super(ChainHistoryExport, self).__init__('') 87 self.history = history 88 self.process_error_result = process_error_result 89 90 91class ChainInternalResult: 92 def __init__(self, type_id, str_data, data): 93 self.type_id = type_id 94 self.str_data = str_data 95 self.data = data 96 97 def __str__(self): 98 return self.str_data 99 100 101class ChainInternalResultType(Enum): 102 # class CriteriaType(): # much more efficient than Enum inheritance 103 built_in_exception__chain_link_failed = 0 104 built_in_exception__bad_history_import = 1 105 external_exception = 2 106 link_did_not_returned_an_answer = 3 107 108 109class Chain: 110 def __init__(self, chain_id=None, chain_info=None, global_link_results_criteria=None, 111 raise_exceptions=False, save_debug_trace=False, closeable=True): 112 """ 113 114 :param chain_id: 115 :param chain_info: 116 :param global_link_results_criteria: will be set to ValueType(CriteriaType.optional, set()) if None; 117 in this case all links are required. 118 :param raise_exceptions: 119 :param save_debug_trace: 120 :param closeable: 121 :return: 122 """ 123 # Use only ValueType(CriteriaType.optional, ...) or ValueType(CriteriaType.needed, set()). 124 # Other will be ignored here. 125 # You may use global_link_results_criteria=ValueType(CriteriaType.optional, set()) to create criteria 126 # "no fails in any link" 127 self._chain_id = chain_id 128 self._chain_info = chain_info 129 self._internal_links_index = IDGenerator() 130 self._reserve_link_id_generator = IDGenerator(GeneratorType.guid_string) 131 self._criteria_list = list() 132 global_link_results_criteria = global_link_results_criteria or ValueType(CriteriaType.optional, set()) 133 if global_link_results_criteria is not None: 134 self._criteria_list.append(global_link_results_criteria) 135 self._raise_exceptions = raise_exceptions 136 self._save_debug_trace = save_debug_trace 137 self._closeable = closeable 138 self._full_history = list() 139 self._links_library = dict() 140 self._all_made_links = set() 141 self._good_links = set() 142 self._bad_links = set() 143 144 self._current_link_id = None 145 self._current_link_info = None 146 self._current_link_result = None 147 self._closed = False 148 149 self._bool_result = ValueCache() 150 151 # def _push_criteria(self, set_of_needed_links=None, set_of_optional_links=None): 152 def _push_criteria(self, link_results_criteria): 153 # Do not use! 154 self._bool_result() 155 self._criteria_list.append(link_results_criteria) 156 157 def _pop_criteria(self): 158 # Do not use! 159 # May raise exception if len(self.criteria_list)==0, but this is OK. 160 self._bool_result() 161 return self._criteria_list.pop() 162 163 def read_criteria(self): 164 criteria = None 165 if self._criteria_list: 166 criteria = self._criteria_list[-1] 167 return criteria 168 169 def _push_link_info(self, link_id, link_info=None): 170 self._current_link_id = link_id 171 self._current_link_info = link_info 172 self._current_link_result = None 173 174 def _pop_link_info(self): 175 self._current_link_id = None 176 self._current_link_info = None 177 self._current_link_result = None 178 179 def push_result(self, bool_result, info_or_data=None): 180 self._current_link_result = (bool_result, info_or_data) 181 182 def push_result_c(self, result): 183 # "class" version: to use when result = ValueExistence() 184 self._current_link_result = (result.existence, result.result) 185 186 def read_link_result_link(self, link_id): 187 # result is NOT protected from changing! 188 original_result_data = self._links_library[link_id][3] 189 result = ValueExistence(original_result_data[0], original_result_data[1]) 190 # result = self._links_library[link_id][3] 191 return result 192 193 def read_link_result_copy(self, link_id): 194 original_result_data = self._links_library[link_id][3] 195 result = ValueExistence(original_result_data[0], copy.copy(original_result_data[1])) 196 return result 197 198 def read_link_result_deepcopy(self, link_id): 199 original_result_data = self._links_library[link_id][3] 200 result = ValueExistence(original_result_data[0], copy.deepcopy(original_result_data[1])) 201 return result 202 203 def _save_link_result(self, ignore_link_result_criteria=None): 204 # ignore_link_result_criteria = ignore_link_result_criteria or IgnoreLinkResultCriteriaType.do_not_ignore 205 if ((IgnoreLinkResultCriteriaType.ignore_if_failed == ignore_link_result_criteria) and 206 (not self._current_link_result[0])) \ 207 or ((IgnoreLinkResultCriteriaType.ignore_if_successful == ignore_link_result_criteria) and 208 self._current_link_result[0]): 209 return 210 211 self._bool_result() 212 import_depth = 0 213 full_link_info = (self._internal_links_index(), self._current_link_id, self._current_link_info, 214 self._current_link_result, import_depth) 215 self._full_history.append(full_link_info) 216 self._links_library[self._current_link_id] = full_link_info 217 self._all_made_links.add(self._current_link_id) 218 if self._current_link_result[0]: 219 self._good_links.add(self._current_link_id) 220 else: 221 self._bad_links.add(self._current_link_id) 222 223 def __bool__(self): 224 if self._bool_result: 225 return self._bool_result.get() 226 else: 227 current_criteria = self.read_criteria() 228 result = True 229 if CriteriaType.needed == current_criteria: 230 if len(current_criteria.result) != len(current_criteria.result & self._good_links): 231 result = False 232 elif CriteriaType.optional == current_criteria: 233 if len(self._bad_links - current_criteria.result) != 0: 234 result = False 235 elif CriteriaType.any == current_criteria: 236 result = True 237 elif CriteriaType.forbidden == current_criteria: 238 if len(current_criteria.result) != len(current_criteria.result & self._bad_links): 239 result = False 240 elif CriteriaType.not_successful == current_criteria: 241 if len(current_criteria.result & self._good_links) != 0: 242 result = False 243 self._bool_result.set(result) 244 return result 245 246 def __nonzero__(self): 247 return self.__bool__() 248 249 @staticmethod 250 def _link_list_to_str(link_list): 251 links_str = ',\n'.join('(index({}), depth({}), ID({}), INFO({}), RESULT({}))'.format(str(another_link[0]), 252 str(another_link[4]), 253 str(another_link[1]), 254 str(another_link[2]), 255 '({}, {})'.format( 256 str(another_link[3][0]), 257 str(another_link[3][1]))) 258 for another_link in link_list) 259 return links_str 260 261 def _link_str_to_chain_str(self, links_str): 262 full_string = '{{{{CONTEXT_HOLDER_ID({}): CONTEXT_HOLDER_INFO({})}}:[\n{}\n]}}'.format( 263 self._chain_id, self._chain_info, links_str) 264 return full_string 265 266 def get_bad_links(self): 267 result = list() 268 for another_link in self._full_history: 269 if not another_link[3][0]: 270 result.append(another_link) 271 return result 272 273 def get_bad_links_str(self): 274 bad_links = self.get_bad_links() 275 full_history_str = self._link_list_to_str(bad_links) 276 full_string = self._link_str_to_chain_str(full_history_str) 277 return full_string 278 279 def raise_bad_links(self): 280 raise ChainHistoryExport(self.get_bad_links()) 281 282 def raise_full_history(self): 283 raise ChainHistoryExport(self._full_history) 284 285 def process_history_import(self, his_ex): 286 history = his_ex.history 287 for another_link in history: 288 full_link_info = (self._internal_links_index(), another_link[1], another_link[2], 289 another_link[3], another_link[4] + 1) 290 self._full_history.append(full_link_info) 291 292 def close(self): 293 self._closed = True 294 295 def _reopen(self): 296 self._closed = False 297 298 def __str__(self): 299 full_history_str = self._link_list_to_str(self._full_history) 300 full_string = self._link_str_to_chain_str(full_history_str) 301 return full_string 302 303 def __call__(self, *args, **kwargs): 304 return link(self, *args, **kwargs) 305 306 def chain(self, *args, **kwargs): 307 return self.__call__(*args, **kwargs) 308 309 310@contextmanager 311def link(chain, link_id, link_info=None, link_results_criteria=None, ignore_link_result_criteria=None): 312 if link_id is None: 313 new_id = chain._reserve_link_id_generator() 314 link_id = (new_id, new_id) 315 316 if chain._closeable and chain._closed: 317 raise ChainClosed(chain, link_id, link_info) 318 319 chain._push_link_info(link_id, link_info) 320 if link_results_criteria is not None: 321 chain._push_criteria(link_results_criteria) 322 need_to_save_link_result = True 323 try: 324 yield chain 325 except ChainLinkFailed as exc: 326 result_info = None 327 if exc.args: 328 result_info = exc.args[0] 329 chain.push_result(False, ChainInternalResult( 330 ChainInternalResultType.built_in_exception__chain_link_failed, 331 'CHAIN INTERNAL RESULT. BUILT-IN EXCEPTION: ChainLinkFailed ({})'.format(result_info), result_info)) 332 except ChainHistoryExport as export: 333 chain.process_history_import(export) 334 if export.process_error_result: 335 chain.push_result(False, ChainInternalResult( 336 ChainInternalResultType.built_in_exception__bad_history_import, 337 'CHAIN INTERNAL RESULT. BUILT-IN EXCEPTION: BAD HISTORY IMPORT EXCEPTION', None)) 338 except: 339 exc = sys.exc_info() 340 exc_type, exc_obj, exc_tb = exc 341 tb_full_file_name = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] 342 tb_line_number = exc_tb.tb_lineno 343 tb_function_name = str() 344 tb_text = str() 345 346 tb_list = traceback.extract_tb(exc_tb, 2) 347 if len(tb_list) >= 2: 348 actual_tb = tb_list[1] 349 tb_full_file_name, tb_line_number, tb_function_name, tb_text = actual_tb 350 351 exception = exc 352 error_str = '{} {}'.format(str(exception[0]), str(exception[1].args[0])) 353 # print('+++', error_str) 354 formatted_traceback = traceback.format_exception(exception[0], exception[1], exception[2]) 355 exception = exception[:2] + (formatted_traceback,) 356 trace_str = ''.join(exception[2]) 357 if chain._save_debug_trace: 358 result_string = 'CHAIN INTERNAL RESULT. CODE EXCEPTION "{}" AT "{}":{} in {} WITH TRACE: \n' \ 359 '{}\n' \ 360 '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~' \ 361 ''.format(error_str, tb_full_file_name, tb_line_number, tb_function_name, trace_str) 362 else: 363 result_string = 'CHAIN INTERNAL RESULT. CODE EXCEPTION "{}" AT "{}":{} in {}'.format( 364 error_str, tb_full_file_name, tb_line_number, tb_function_name) 365 chain.push_result(False, ChainInternalResult( 366 ChainInternalResultType.external_exception, result_string, exc)) 367 # print(result_string) 368 # _chain_reader_runner__chain.push_result(False, sys.exc_info()[1]) 369 if chain._raise_exceptions: 370 need_to_save_link_result = False 371 chain._save_link_result() 372 chain.raise_bad_links() 373 # raise 374 else: 375 if chain._current_link_result is None: 376 # _chain_reader_runner__chain.push_result(True) 377 chain.push_result(False, ChainInternalResult( 378 ChainInternalResultType.link_did_not_returned_an_answer, 379 'CHAIN INTERNAL RESULT. Link DID NOT RETURN RESULT', None)) 380 finally: 381 if need_to_save_link_result: 382 chain._save_link_result(ignore_link_result_criteria) 383 if link_results_criteria is not None: 384 chain._pop_criteria() 385 chain._pop_link_info() 386 387 388def link__function(target_function): 389 """ 390 Parameters: chain__chain= (required) 391 , chain__link_id= (required) 392 , chain__link_info= (optional) 393 , chain__link_results_criteria= (optional) 394 , chain__ignore_link_result_criteria= (optional). 395 Parameters passed to the target_function: chain__chain (after local link configuration). 396 :param target_function: function 397 :return: 398 """ 399 400 def new_target_function(*args, **kwargs): 401 chain = None 402 if 'chain__chain' in kwargs: 403 chain = kwargs['chain__chain'] 404 del kwargs['chain__chain'] 405 else: 406 raise ChainFunctionParameterNeeded('chain__chain') 407 408 link_id = None 409 if 'chain__link_id' in kwargs: 410 link_id = kwargs['chain__link_id'] 411 del kwargs['chain__link_id'] 412 else: 413 raise ChainFunctionParameterNeeded('chain__link_id') 414 415 link_info = None 416 if 'chain__link_info' in kwargs: 417 link_info = kwargs['chain__link_info'] 418 del kwargs['chain__link_info'] 419 420 link_results_criteria = None 421 if 'chain__link_results_criteria' in kwargs: 422 link_results_criteria = kwargs['chain__link_results_criteria'] 423 del kwargs['chain__link_results_criteria'] 424 425 ignore_link_result_criteria = None 426 if 'chain__ignore_link_result_criteria' in kwargs: 427 ignore_link_result_criteria = kwargs['chain__ignore_link_result_criteria'] 428 del kwargs['chain__ignore_link_result_criteria'] 429 430 target_function_result = None 431 with link(chain, link_id, link_info, link_results_criteria, ignore_link_result_criteria) as \ 432 context: 433 kwargs['chain__chain'] = context 434 target_function_result = target_function(*args, **kwargs) 435 436 return target_function_result 437 438 return new_target_function 439 440 441class _ChainRunner: 442 def __init__(self, current_globals, chain, link_id=None, link_info=None, link_results_criteria=None, 443 ignore_link_result_criteria=None, function_result_criteria=None): 444 self._chain_runner__current_globals = current_globals 445 self._chain_runner__chain = chain 446 self._chain_runner__link_id = link_id 447 self._chain_runner__link_info = link_info 448 self._chain_runner__link_results_criteria = link_results_criteria 449 self._chain_runner__ignore_link_result_criteria = ignore_link_result_criteria 450 451 def __getattr__(self, name): 452 target_functor = None 453 if name in self._chain_runner__current_globals: 454 target_functor = self._chain_runner__current_globals[name] 455 else: 456 raise AttributeError(name) 457 458 def new_target_function(*args, **kwargs): 459 target_function_result = None 460 link_id = self._chain_runner__link_id or str(target_functor) 461 with link(self._chain_runner__chain, link_id, self._chain_runner__link_info, 462 self._chain_runner__link_results_criteria, 463 self._chain_runner__ignore_link_result_criteria) as context: 464 kwargs['chain__chain'] = context 465 target_function_result = target_functor(*args, **kwargs) 466 467 return target_function_result 468 469 return new_target_function 470 471 472class ChainRunner: 473 def __init__(self, current_globals, chain): 474 self.current_globals = current_globals 475 self.chain = chain 476 477 def __call__(self, link_id=None, link_info=None, link_results_criteria=None, 478 ignore_link_result_criteria=None): 479 result = _ChainRunner(self.current_globals, self.chain, link_id, link_info, link_results_criteria, 480 ignore_link_result_criteria) 481 return result 482 483 484class _ChainCallRunner: 485 def __init__(self, chain, link_id=None, link_info=None, link_results_criteria=None, 486 ignore_link_result_criteria=None, function_result_criteria=None): 487 self._chain_runner__chain = chain 488 self._chain_runner__link_id = link_id 489 self._chain_runner__link_info = link_info 490 self._chain_runner__link_results_criteria = link_results_criteria 491 self._chain_runner__ignore_link_result_criteria = ignore_link_result_criteria 492 493 def __call__(self, target_functor, *args, **kwargs): 494 target_function_result = None 495 link_id = self._chain_runner__link_id or str(target_functor) 496 with link(self._chain_runner__chain, link_id, self._chain_runner__link_info, 497 self._chain_runner__link_results_criteria, 498 self._chain_runner__ignore_link_result_criteria) as context: 499 kwargs['chain__chain'] = context 500 target_function_result = target_functor(*args, **kwargs) 501 502 return target_function_result 503 504 505class ChainCallRunner: 506 def __init__(self, chain): 507 self.chain = chain 508 509 def __call__(self, link_id=None, link_info=None, link_results_criteria=None, 510 ignore_link_result_criteria=None): 511 result = _ChainCallRunner(self.chain, link_id, link_info, link_results_criteria, 512 ignore_link_result_criteria) 513 return result 514 515 516def link__function__simple(target_function): 517 """ 518 Parameters: chain__chain= (required) 519 , chain__link_id= (optional) (default value == str(target_function)) 520 , chain__link_results_criteria= (optional) 521 , chain__ignore_link_result_criteria= (optional). 522 Parameters passed to the target_function: . 523 :param target_function: function 524 :return: 525 """ 526 527 def new_target_function(*args, **kwargs): 528 chain = None 529 if 'chain__chain' in kwargs: 530 chain = kwargs['chain__chain'] 531 del kwargs['chain__chain'] 532 else: 533 raise ChainFunctionParameterNeeded('chain__chain') 534 535 # link_id = '__UNNAMED_FUNCTION_SIMPLE_LINK__' 536 link_id = str(target_function) 537 if 'chain__link_id' in kwargs: 538 link_id = kwargs['chain__link_id'] 539 del kwargs['chain__link_id'] 540 541 link_results_criteria = None 542 if 'chain__link_results_criteria' in kwargs: 543 link_results_criteria = kwargs['chain__link_results_criteria'] 544 del kwargs['chain__link_results_criteria'] 545 546 ignore_link_result_criteria = None 547 if 'chain__ignore_link_result_criteria' in kwargs: 548 ignore_link_result_criteria = kwargs['chain__ignore_link_result_criteria'] 549 del kwargs['chain__ignore_link_result_criteria'] 550 551 target_function_result = None 552 with link(chain, link_id, None, link_results_criteria, ignore_link_result_criteria) as context: 553 if context: 554 target_function_result = target_function(*args, **kwargs) 555 context.push_result(True, target_function_result) 556 557 return target_function_result 558 559 return new_target_function 560 561 562class _ChainRunnerSimple: 563 def __init__(self, current_globals, chain, link_id=None, link_info=None, link_results_criteria=None, 564 ignore_link_result_criteria=None, function_result_criteria=None): 565 self._chain_runner_simple__current_globals = current_globals 566 self._chain_runner_simple__chain = chain 567 self._chain_runner_simple__link_id = link_id 568 self._chain_runner_simple__link_info = link_info 569 self._chain_runner_simple__link_results_criteria = link_results_criteria 570 self._chain_runner_simple__ignore_link_result_criteria = ignore_link_result_criteria 571 self._chain_runner_simple__function_result_criteria = function_result_criteria or (lambda result: True) 572 573 def __getattr__(self, name): 574 target_functor = None 575 if name in self._chain_runner_simple__current_globals: 576 target_functor = self._chain_runner_simple__current_globals[name] 577 else: 578 raise AttributeError(name) 579 580 def new_target_function(*args, **kwargs): 581 target_function_result = None 582 link_id = self._chain_runner_simple__link_id or str(target_functor) 583 with link(self._chain_runner_simple__chain, link_id, self._chain_runner_simple__link_info, 584 self._chain_runner_simple__link_results_criteria, 585 self._chain_runner_simple__ignore_link_result_criteria) as context: 586 if context: 587 target_function_result = target_functor(*args, **kwargs) 588 is_good_result = self._chain_runner_simple__function_result_criteria(target_function_result) 589 context.push_result(is_good_result, target_function_result) 590 591 return target_function_result 592 593 return new_target_function 594 595 596class ChainUniRunner: 597 def __init__(self, current_globals, chain, simple_mode=False, function_result_criteria=None): 598 self.current_globals = current_globals 599 self.chain = chain 600 self.simple_mode = simple_mode 601 self.default_function_result_criteria = function_result_criteria or (lambda result: True) 602 self.function_result_criteria = self.default_function_result_criteria 603 604 self.runner_class = _ChainRunner 605 if self.simple_mode: 606 self.runner_class = _ChainRunnerSimple 607 608 def set_function_result_criteria(self, result_criteria_computer): 609 self.function_result_criteria = result_criteria_computer 610 611 def reset_function_result_criteria(self): 612 self.function_result_criteria = self.default_function_result_criteria 613 614 def __call__(self, link_id=None, link_info=None, link_results_criteria=None, 615 ignore_link_result_criteria=None): 616 result = self.runner_class(self.current_globals, self.chain, link_id, link_info, 617 link_results_criteria, ignore_link_result_criteria, self.function_result_criteria) 618 return result 619 620 621class _ChainCallRunnerSimple: 622 def __init__(self, chain, link_id=None, link_info=None, link_results_criteria=None, 623 ignore_link_result_criteria=None, function_result_criteria=None): 624 self._chain_runner_simple__chain = chain 625 self._chain_runner_simple__link_id = link_id 626 self._chain_runner_simple__link_info = link_info 627 self._chain_runner_simple__link_results_criteria = link_results_criteria 628 self._chain_runner_simple__ignore_link_result_criteria = ignore_link_result_criteria 629 self._chain_runner_simple__function_result_criteria = function_result_criteria or (lambda result: True) 630 631 def __call__(self, target_functor, *args, **kwargs): 632 target_function_result = None 633 link_id = self._chain_runner_simple__link_id or str(target_functor) 634 with link(self._chain_runner_simple__chain, link_id, self._chain_runner_simple__link_info, 635 self._chain_runner_simple__link_results_criteria, 636 self._chain_runner_simple__ignore_link_result_criteria) as context: 637 if context: 638 target_function_result = target_functor(*args, **kwargs) 639 is_good_result = self._chain_runner_simple__function_result_criteria(target_function_result) 640 context.push_result(is_good_result, target_function_result) 641 642 return target_function_result 643 644 645class ChainUniCallRunner: 646 def __init__(self, chain, simple_mode=False, function_result_criteria=None): 647 self.chain = chain 648 self.simple_mode = simple_mode 649 self.default_function_result_criteria = function_result_criteria or (lambda result: True) 650 self.function_result_criteria = self.default_function_result_criteria 651 652 self.runner_class = _ChainCallRunner 653 if self.simple_mode: 654 self.runner_class = _ChainCallRunnerSimple 655 656 def set_function_result_criteria(self, result_criteria_computer): 657 self.function_result_criteria = result_criteria_computer 658 659 def reset_function_result_criteria(self): 660 self.function_result_criteria = self.default_function_result_criteria 661 662 def __call__(self, link_id=None, link_info=None, link_results_criteria=None, 663 ignore_link_result_criteria=None): 664 result = self.runner_class(self.chain, link_id, link_info, 665 link_results_criteria, ignore_link_result_criteria, self.function_result_criteria) 666 return result 667 668 669class _ChainValRunner: 670 def __init__(self, chain, link_id=None, link_info=None, link_results_criteria=None, 671 ignore_link_result_criteria=None, function_result_criteria=None, reaction_to_the_result=None): 672 self._chain_runner_simple__chain = chain 673 self._chain_runner_simple__link_id = link_id 674 self._chain_runner_simple__link_info = link_info 675 self._chain_runner_simple__link_results_criteria = link_results_criteria 676 self._chain_runner_simple__ignore_link_result_criteria = ignore_link_result_criteria 677 self._chain_runner_simple__function_result_criteria = function_result_criteria or (lambda result: True) 678 self._chain_runner_simple__reaction_to_the_result = reaction_to_the_result 679 680 def __call__(self, functor_result): 681 target_function_result = functor_result 682 link_id = self._chain_runner_simple__link_id 683 with link(self._chain_runner_simple__chain, link_id, self._chain_runner_simple__link_info, 684 self._chain_runner_simple__link_results_criteria, 685 self._chain_runner_simple__ignore_link_result_criteria) as context: 686 if context: 687 is_good_result = self._chain_runner_simple__function_result_criteria(target_function_result) 688 if self._chain_runner_simple__reaction_to_the_result is not None: 689 verdict = self._chain_runner_simple__reaction_to_the_result(is_good_result, target_function_result) 690 target_function_result = (target_function_result, verdict) 691 context.push_result(is_good_result, target_function_result) 692 693 return functor_result 694 695 696class ChainValRunner: 697 def __init__(self, chain, function_result_criteria=None, reaction_to_the_result=None): 698 self.chain = chain 699 self.default_function_result_criteria = function_result_criteria or (lambda result: True) 700 self.function_result_criteria = self.default_function_result_criteria 701 self.reaction_to_the_result = reaction_to_the_result 702 703 def set_function_result_criteria(self, result_criteria_computer): 704 self.function_result_criteria = result_criteria_computer 705 706 def reset_function_result_criteria(self): 707 self.function_result_criteria = self.default_function_result_criteria 708 709 def __call__(self, link_id=None, link_info=None, link_results_criteria=None, 710 ignore_link_result_criteria=None): 711 result = _ChainValRunner(self.chain, link_id, link_info, 712 link_results_criteria, ignore_link_result_criteria, 713 self.function_result_criteria, self.reaction_to_the_result) 714 return result 715 716 717@contextmanager 718def chain_reader(chain, link_results_criteria=None, close=False): 719 if link_results_criteria is not None: 720 chain._push_criteria(link_results_criteria) 721 try: 722 yield chain 723 except: 724 raise 725 finally: 726 if link_results_criteria is not None: 727 chain._pop_criteria() 728 if close: 729 chain.close() 730 731 732def chain_reader__function(target_function): 733 """ 734 Parameters: chain__chain= (required), chain__link_results_criteria= (optional), chain__close= (optional). 735 Parameters passed to the target_function: chain__chain (after local link configuration). 736 :param target_function: function 737 :return: 738 """ 739 740 def new_target_function(*args, **kwargs): 741 chain = None 742 if 'chain__chain' in kwargs: 743 chain = kwargs['chain__chain'] 744 del kwargs['chain__chain'] 745 else: 746 raise ChainFunctionParameterNeeded('chain__chain') 747 748 link_results_criteria = None 749 if 'chain__link_results_criteria' in kwargs: 750 link_results_criteria = kwargs['chain__link_results_criteria'] 751 del kwargs['chain__link_results_criteria'] 752 753 close = None 754 if 'chain__close' in kwargs: 755 close = kwargs['chain__close'] 756 del kwargs['chain__close'] 757 758 target_function_result = None 759 with chain_reader(chain, link_results_criteria, close) as context: 760 kwargs['chain__chain'] = context 761 target_function_result = target_function(*args, **kwargs) 762 763 return target_function_result 764 765 return new_target_function 766 767 768class _ChainReaderRunner: 769 def __init__(self, current_globals, chain, link_results_criteria=None, close=False): 770 self._chain_reader_runner__current_globals = current_globals 771 self._chain_reader_runner__chain = chain 772 self._chain_reader_runner__link_results_criteria = link_results_criteria 773 self._chain_reader_runner__close = close 774 775 def __getattr__(self, name): 776 target_functor = None 777 if name in self._chain_reader_runner__current_globals: 778 target_functor = self._chain_reader_runner__current_globals[name] 779 else: 780 raise AttributeError(name) 781 782 def new_target_function(*args, **kwargs): 783 target_function_result = None 784 with chain_reader(self._chain_reader_runner__chain, 785 self._chain_reader_runner__link_results_criteria, 786 self._chain_reader_runner__close) as context: 787 kwargs['chain__chain'] = context 788 target_function_result = target_functor(*args, **kwargs) 789 790 return target_function_result 791 792 return new_target_function 793 794 795class ChainReaderRunner: 796 def __init__(self, current_globals, chain): 797 self.current_globals = current_globals 798 self.chain = chain 799 800 def __call__(self, link_results_criteria=None, close=False): 801 result = _ChainReaderRunner(self.current_globals, self.chain, link_results_criteria, close) 802 return result 803 804 805class _ChainReaderCallRunner: 806 def __init__(self, chain, link_results_criteria=None, close=False): 807 self._chain_reader_runner__chain = chain 808 self._chain_reader_runner__link_results_criteria = link_results_criteria 809 self._chain_reader_runner__close = close 810 811 def __call__(self, target_functor, *args, **kwargs): 812 target_function_result = None 813 with chain_reader(self._chain_reader_runner__chain, 814 self._chain_reader_runner__link_results_criteria, 815 self._chain_reader_runner__close) as context: 816 kwargs['chain__chain'] = context 817 target_function_result = target_functor(*args, **kwargs) 818 819 return target_function_result 820 821 822class ChainReaderCallRunner: 823 def __init__(self, chain): 824 self.chain = chain 825 826 def __call__(self, link_results_criteria=None, close=False): 827 result = _ChainReaderCallRunner(self.chain, link_results_criteria, close) 828 return result
45class ChainLinkFailed(Exception): pass
Common base class for all non-exit exceptions.
Inherited Members
- builtins.Exception
- Exception
- builtins.BaseException
- with_traceback
- args
48class ChainClosed(Exception): 49 """ 50 link considers it ordinary external exception 51 """ 52 53 def __init__(self, chain, link_id, link_info): 54 super(ChainClosed, self).__init__('Content Holder is closed. ' 55 'Content Holder ID: {}; ' 56 'Content Holder Info: {}; ' 57 'Link ID: {}; ' 58 'Link Info {}'.format(str(chain._chain_id), 59 str(chain._chain_info), 60 str(link_id), 61 str(link_info))) 62 self.chain = chain 63 self.link_id = link_id 64 self.link_info = link_info
link considers it ordinary external exception
53 def __init__(self, chain, link_id, link_info): 54 super(ChainClosed, self).__init__('Content Holder is closed. ' 55 'Content Holder ID: {}; ' 56 'Content Holder Info: {}; ' 57 'Link ID: {}; ' 58 'Link Info {}'.format(str(chain._chain_id), 59 str(chain._chain_info), 60 str(link_id), 61 str(link_info))) 62 self.chain = chain 63 self.link_id = link_id 64 self.link_info = link_info
Inherited Members
- builtins.BaseException
- with_traceback
- args
67class ChainFunctionParameterNeeded(Exception): pass
Common base class for all non-exit exceptions.
Inherited Members
- builtins.Exception
- Exception
- builtins.BaseException
- with_traceback
- args
70class CriteriaType(Enum): 71 # class CriteriaType(): # much more efficient than Enum inheritance 72 needed = 0 # only set of this links is needed (should be already successfully done) 73 optional = 1 # all links are needed except of this set of links 74 any = 2 # any result will fit criteria 75 forbidden = 3 # set of this links should be already failed 76 not_successful = 4 # set of this links should not be successfully done (also may not start) at the check time
An enumeration.
Inherited Members
- enum.Enum
- name
- value
79class IgnoreLinkResultCriteriaType(Enum): 80 do_not_ignore = 0 81 ignore_if_failed = 1 82 ignore_if_successful = 2
An enumeration.
Inherited Members
- enum.Enum
- name
- value
85class ChainHistoryExport(Exception): 86 def __init__(self, history, process_error_result=True): 87 super(ChainHistoryExport, self).__init__('') 88 self.history = history 89 self.process_error_result = process_error_result
Common base class for all non-exit exceptions.
Inherited Members
- builtins.BaseException
- with_traceback
- args
92class ChainInternalResult: 93 def __init__(self, type_id, str_data, data): 94 self.type_id = type_id 95 self.str_data = str_data 96 self.data = data 97 98 def __str__(self): 99 return self.str_data
102class ChainInternalResultType(Enum): 103 # class CriteriaType(): # much more efficient than Enum inheritance 104 built_in_exception__chain_link_failed = 0 105 built_in_exception__bad_history_import = 1 106 external_exception = 2 107 link_did_not_returned_an_answer = 3
An enumeration.
Inherited Members
- enum.Enum
- name
- value
110class Chain: 111 def __init__(self, chain_id=None, chain_info=None, global_link_results_criteria=None, 112 raise_exceptions=False, save_debug_trace=False, closeable=True): 113 """ 114 115 :param chain_id: 116 :param chain_info: 117 :param global_link_results_criteria: will be set to ValueType(CriteriaType.optional, set()) if None; 118 in this case all links are required. 119 :param raise_exceptions: 120 :param save_debug_trace: 121 :param closeable: 122 :return: 123 """ 124 # Use only ValueType(CriteriaType.optional, ...) or ValueType(CriteriaType.needed, set()). 125 # Other will be ignored here. 126 # You may use global_link_results_criteria=ValueType(CriteriaType.optional, set()) to create criteria 127 # "no fails in any link" 128 self._chain_id = chain_id 129 self._chain_info = chain_info 130 self._internal_links_index = IDGenerator() 131 self._reserve_link_id_generator = IDGenerator(GeneratorType.guid_string) 132 self._criteria_list = list() 133 global_link_results_criteria = global_link_results_criteria or ValueType(CriteriaType.optional, set()) 134 if global_link_results_criteria is not None: 135 self._criteria_list.append(global_link_results_criteria) 136 self._raise_exceptions = raise_exceptions 137 self._save_debug_trace = save_debug_trace 138 self._closeable = closeable 139 self._full_history = list() 140 self._links_library = dict() 141 self._all_made_links = set() 142 self._good_links = set() 143 self._bad_links = set() 144 145 self._current_link_id = None 146 self._current_link_info = None 147 self._current_link_result = None 148 self._closed = False 149 150 self._bool_result = ValueCache() 151 152 # def _push_criteria(self, set_of_needed_links=None, set_of_optional_links=None): 153 def _push_criteria(self, link_results_criteria): 154 # Do not use! 155 self._bool_result() 156 self._criteria_list.append(link_results_criteria) 157 158 def _pop_criteria(self): 159 # Do not use! 160 # May raise exception if len(self.criteria_list)==0, but this is OK. 161 self._bool_result() 162 return self._criteria_list.pop() 163 164 def read_criteria(self): 165 criteria = None 166 if self._criteria_list: 167 criteria = self._criteria_list[-1] 168 return criteria 169 170 def _push_link_info(self, link_id, link_info=None): 171 self._current_link_id = link_id 172 self._current_link_info = link_info 173 self._current_link_result = None 174 175 def _pop_link_info(self): 176 self._current_link_id = None 177 self._current_link_info = None 178 self._current_link_result = None 179 180 def push_result(self, bool_result, info_or_data=None): 181 self._current_link_result = (bool_result, info_or_data) 182 183 def push_result_c(self, result): 184 # "class" version: to use when result = ValueExistence() 185 self._current_link_result = (result.existence, result.result) 186 187 def read_link_result_link(self, link_id): 188 # result is NOT protected from changing! 189 original_result_data = self._links_library[link_id][3] 190 result = ValueExistence(original_result_data[0], original_result_data[1]) 191 # result = self._links_library[link_id][3] 192 return result 193 194 def read_link_result_copy(self, link_id): 195 original_result_data = self._links_library[link_id][3] 196 result = ValueExistence(original_result_data[0], copy.copy(original_result_data[1])) 197 return result 198 199 def read_link_result_deepcopy(self, link_id): 200 original_result_data = self._links_library[link_id][3] 201 result = ValueExistence(original_result_data[0], copy.deepcopy(original_result_data[1])) 202 return result 203 204 def _save_link_result(self, ignore_link_result_criteria=None): 205 # ignore_link_result_criteria = ignore_link_result_criteria or IgnoreLinkResultCriteriaType.do_not_ignore 206 if ((IgnoreLinkResultCriteriaType.ignore_if_failed == ignore_link_result_criteria) and 207 (not self._current_link_result[0])) \ 208 or ((IgnoreLinkResultCriteriaType.ignore_if_successful == ignore_link_result_criteria) and 209 self._current_link_result[0]): 210 return 211 212 self._bool_result() 213 import_depth = 0 214 full_link_info = (self._internal_links_index(), self._current_link_id, self._current_link_info, 215 self._current_link_result, import_depth) 216 self._full_history.append(full_link_info) 217 self._links_library[self._current_link_id] = full_link_info 218 self._all_made_links.add(self._current_link_id) 219 if self._current_link_result[0]: 220 self._good_links.add(self._current_link_id) 221 else: 222 self._bad_links.add(self._current_link_id) 223 224 def __bool__(self): 225 if self._bool_result: 226 return self._bool_result.get() 227 else: 228 current_criteria = self.read_criteria() 229 result = True 230 if CriteriaType.needed == current_criteria: 231 if len(current_criteria.result) != len(current_criteria.result & self._good_links): 232 result = False 233 elif CriteriaType.optional == current_criteria: 234 if len(self._bad_links - current_criteria.result) != 0: 235 result = False 236 elif CriteriaType.any == current_criteria: 237 result = True 238 elif CriteriaType.forbidden == current_criteria: 239 if len(current_criteria.result) != len(current_criteria.result & self._bad_links): 240 result = False 241 elif CriteriaType.not_successful == current_criteria: 242 if len(current_criteria.result & self._good_links) != 0: 243 result = False 244 self._bool_result.set(result) 245 return result 246 247 def __nonzero__(self): 248 return self.__bool__() 249 250 @staticmethod 251 def _link_list_to_str(link_list): 252 links_str = ',\n'.join('(index({}), depth({}), ID({}), INFO({}), RESULT({}))'.format(str(another_link[0]), 253 str(another_link[4]), 254 str(another_link[1]), 255 str(another_link[2]), 256 '({}, {})'.format( 257 str(another_link[3][0]), 258 str(another_link[3][1]))) 259 for another_link in link_list) 260 return links_str 261 262 def _link_str_to_chain_str(self, links_str): 263 full_string = '{{{{CONTEXT_HOLDER_ID({}): CONTEXT_HOLDER_INFO({})}}:[\n{}\n]}}'.format( 264 self._chain_id, self._chain_info, links_str) 265 return full_string 266 267 def get_bad_links(self): 268 result = list() 269 for another_link in self._full_history: 270 if not another_link[3][0]: 271 result.append(another_link) 272 return result 273 274 def get_bad_links_str(self): 275 bad_links = self.get_bad_links() 276 full_history_str = self._link_list_to_str(bad_links) 277 full_string = self._link_str_to_chain_str(full_history_str) 278 return full_string 279 280 def raise_bad_links(self): 281 raise ChainHistoryExport(self.get_bad_links()) 282 283 def raise_full_history(self): 284 raise ChainHistoryExport(self._full_history) 285 286 def process_history_import(self, his_ex): 287 history = his_ex.history 288 for another_link in history: 289 full_link_info = (self._internal_links_index(), another_link[1], another_link[2], 290 another_link[3], another_link[4] + 1) 291 self._full_history.append(full_link_info) 292 293 def close(self): 294 self._closed = True 295 296 def _reopen(self): 297 self._closed = False 298 299 def __str__(self): 300 full_history_str = self._link_list_to_str(self._full_history) 301 full_string = self._link_str_to_chain_str(full_history_str) 302 return full_string 303 304 def __call__(self, *args, **kwargs): 305 return link(self, *args, **kwargs) 306 307 def chain(self, *args, **kwargs): 308 return self.__call__(*args, **kwargs)
111 def __init__(self, chain_id=None, chain_info=None, global_link_results_criteria=None, 112 raise_exceptions=False, save_debug_trace=False, closeable=True): 113 """ 114 115 :param chain_id: 116 :param chain_info: 117 :param global_link_results_criteria: will be set to ValueType(CriteriaType.optional, set()) if None; 118 in this case all links are required. 119 :param raise_exceptions: 120 :param save_debug_trace: 121 :param closeable: 122 :return: 123 """ 124 # Use only ValueType(CriteriaType.optional, ...) or ValueType(CriteriaType.needed, set()). 125 # Other will be ignored here. 126 # You may use global_link_results_criteria=ValueType(CriteriaType.optional, set()) to create criteria 127 # "no fails in any link" 128 self._chain_id = chain_id 129 self._chain_info = chain_info 130 self._internal_links_index = IDGenerator() 131 self._reserve_link_id_generator = IDGenerator(GeneratorType.guid_string) 132 self._criteria_list = list() 133 global_link_results_criteria = global_link_results_criteria or ValueType(CriteriaType.optional, set()) 134 if global_link_results_criteria is not None: 135 self._criteria_list.append(global_link_results_criteria) 136 self._raise_exceptions = raise_exceptions 137 self._save_debug_trace = save_debug_trace 138 self._closeable = closeable 139 self._full_history = list() 140 self._links_library = dict() 141 self._all_made_links = set() 142 self._good_links = set() 143 self._bad_links = set() 144 145 self._current_link_id = None 146 self._current_link_info = None 147 self._current_link_result = None 148 self._closed = False 149 150 self._bool_result = ValueCache()
:param chain_id: :param chain_info: :param global_link_results_criteria: will be set to ValueType(CriteriaType.optional, set()) if None; in this case all links are required. :param raise_exceptions: :param save_debug_trace: :param closeable: :return:
311@contextmanager 312def link(chain, link_id, link_info=None, link_results_criteria=None, ignore_link_result_criteria=None): 313 if link_id is None: 314 new_id = chain._reserve_link_id_generator() 315 link_id = (new_id, new_id) 316 317 if chain._closeable and chain._closed: 318 raise ChainClosed(chain, link_id, link_info) 319 320 chain._push_link_info(link_id, link_info) 321 if link_results_criteria is not None: 322 chain._push_criteria(link_results_criteria) 323 need_to_save_link_result = True 324 try: 325 yield chain 326 except ChainLinkFailed as exc: 327 result_info = None 328 if exc.args: 329 result_info = exc.args[0] 330 chain.push_result(False, ChainInternalResult( 331 ChainInternalResultType.built_in_exception__chain_link_failed, 332 'CHAIN INTERNAL RESULT. BUILT-IN EXCEPTION: ChainLinkFailed ({})'.format(result_info), result_info)) 333 except ChainHistoryExport as export: 334 chain.process_history_import(export) 335 if export.process_error_result: 336 chain.push_result(False, ChainInternalResult( 337 ChainInternalResultType.built_in_exception__bad_history_import, 338 'CHAIN INTERNAL RESULT. BUILT-IN EXCEPTION: BAD HISTORY IMPORT EXCEPTION', None)) 339 except: 340 exc = sys.exc_info() 341 exc_type, exc_obj, exc_tb = exc 342 tb_full_file_name = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] 343 tb_line_number = exc_tb.tb_lineno 344 tb_function_name = str() 345 tb_text = str() 346 347 tb_list = traceback.extract_tb(exc_tb, 2) 348 if len(tb_list) >= 2: 349 actual_tb = tb_list[1] 350 tb_full_file_name, tb_line_number, tb_function_name, tb_text = actual_tb 351 352 exception = exc 353 error_str = '{} {}'.format(str(exception[0]), str(exception[1].args[0])) 354 # print('+++', error_str) 355 formatted_traceback = traceback.format_exception(exception[0], exception[1], exception[2]) 356 exception = exception[:2] + (formatted_traceback,) 357 trace_str = ''.join(exception[2]) 358 if chain._save_debug_trace: 359 result_string = 'CHAIN INTERNAL RESULT. CODE EXCEPTION "{}" AT "{}":{} in {} WITH TRACE: \n' \ 360 '{}\n' \ 361 '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~' \ 362 ''.format(error_str, tb_full_file_name, tb_line_number, tb_function_name, trace_str) 363 else: 364 result_string = 'CHAIN INTERNAL RESULT. CODE EXCEPTION "{}" AT "{}":{} in {}'.format( 365 error_str, tb_full_file_name, tb_line_number, tb_function_name) 366 chain.push_result(False, ChainInternalResult( 367 ChainInternalResultType.external_exception, result_string, exc)) 368 # print(result_string) 369 # _chain_reader_runner__chain.push_result(False, sys.exc_info()[1]) 370 if chain._raise_exceptions: 371 need_to_save_link_result = False 372 chain._save_link_result() 373 chain.raise_bad_links() 374 # raise 375 else: 376 if chain._current_link_result is None: 377 # _chain_reader_runner__chain.push_result(True) 378 chain.push_result(False, ChainInternalResult( 379 ChainInternalResultType.link_did_not_returned_an_answer, 380 'CHAIN INTERNAL RESULT. Link DID NOT RETURN RESULT', None)) 381 finally: 382 if need_to_save_link_result: 383 chain._save_link_result(ignore_link_result_criteria) 384 if link_results_criteria is not None: 385 chain._pop_criteria() 386 chain._pop_link_info()
389def link__function(target_function): 390 """ 391 Parameters: chain__chain= (required) 392 , chain__link_id= (required) 393 , chain__link_info= (optional) 394 , chain__link_results_criteria= (optional) 395 , chain__ignore_link_result_criteria= (optional). 396 Parameters passed to the target_function: chain__chain (after local link configuration). 397 :param target_function: function 398 :return: 399 """ 400 401 def new_target_function(*args, **kwargs): 402 chain = None 403 if 'chain__chain' in kwargs: 404 chain = kwargs['chain__chain'] 405 del kwargs['chain__chain'] 406 else: 407 raise ChainFunctionParameterNeeded('chain__chain') 408 409 link_id = None 410 if 'chain__link_id' in kwargs: 411 link_id = kwargs['chain__link_id'] 412 del kwargs['chain__link_id'] 413 else: 414 raise ChainFunctionParameterNeeded('chain__link_id') 415 416 link_info = None 417 if 'chain__link_info' in kwargs: 418 link_info = kwargs['chain__link_info'] 419 del kwargs['chain__link_info'] 420 421 link_results_criteria = None 422 if 'chain__link_results_criteria' in kwargs: 423 link_results_criteria = kwargs['chain__link_results_criteria'] 424 del kwargs['chain__link_results_criteria'] 425 426 ignore_link_result_criteria = None 427 if 'chain__ignore_link_result_criteria' in kwargs: 428 ignore_link_result_criteria = kwargs['chain__ignore_link_result_criteria'] 429 del kwargs['chain__ignore_link_result_criteria'] 430 431 target_function_result = None 432 with link(chain, link_id, link_info, link_results_criteria, ignore_link_result_criteria) as \ 433 context: 434 kwargs['chain__chain'] = context 435 target_function_result = target_function(*args, **kwargs) 436 437 return target_function_result 438 439 return new_target_function
Parameters: chain__chain= (required) , chain__link_id= (required) , chain__link_info= (optional) , chain__link_results_criteria= (optional) , chain__ignore_link_result_criteria= (optional). Parameters passed to the target_function: chain__chain (after local link configuration). :param target_function: function :return:
473class ChainRunner: 474 def __init__(self, current_globals, chain): 475 self.current_globals = current_globals 476 self.chain = chain 477 478 def __call__(self, link_id=None, link_info=None, link_results_criteria=None, 479 ignore_link_result_criteria=None): 480 result = _ChainRunner(self.current_globals, self.chain, link_id, link_info, link_results_criteria, 481 ignore_link_result_criteria) 482 return result
506class ChainCallRunner: 507 def __init__(self, chain): 508 self.chain = chain 509 510 def __call__(self, link_id=None, link_info=None, link_results_criteria=None, 511 ignore_link_result_criteria=None): 512 result = _ChainCallRunner(self.chain, link_id, link_info, link_results_criteria, 513 ignore_link_result_criteria) 514 return result
517def link__function__simple(target_function): 518 """ 519 Parameters: chain__chain= (required) 520 , chain__link_id= (optional) (default value == str(target_function)) 521 , chain__link_results_criteria= (optional) 522 , chain__ignore_link_result_criteria= (optional). 523 Parameters passed to the target_function: . 524 :param target_function: function 525 :return: 526 """ 527 528 def new_target_function(*args, **kwargs): 529 chain = None 530 if 'chain__chain' in kwargs: 531 chain = kwargs['chain__chain'] 532 del kwargs['chain__chain'] 533 else: 534 raise ChainFunctionParameterNeeded('chain__chain') 535 536 # link_id = '__UNNAMED_FUNCTION_SIMPLE_LINK__' 537 link_id = str(target_function) 538 if 'chain__link_id' in kwargs: 539 link_id = kwargs['chain__link_id'] 540 del kwargs['chain__link_id'] 541 542 link_results_criteria = None 543 if 'chain__link_results_criteria' in kwargs: 544 link_results_criteria = kwargs['chain__link_results_criteria'] 545 del kwargs['chain__link_results_criteria'] 546 547 ignore_link_result_criteria = None 548 if 'chain__ignore_link_result_criteria' in kwargs: 549 ignore_link_result_criteria = kwargs['chain__ignore_link_result_criteria'] 550 del kwargs['chain__ignore_link_result_criteria'] 551 552 target_function_result = None 553 with link(chain, link_id, None, link_results_criteria, ignore_link_result_criteria) as context: 554 if context: 555 target_function_result = target_function(*args, **kwargs) 556 context.push_result(True, target_function_result) 557 558 return target_function_result 559 560 return new_target_function
Parameters: chain__chain= (required) , chain__link_id= (optional) (default value == str(target_function)) , chain__link_results_criteria= (optional) , chain__ignore_link_result_criteria= (optional). Parameters passed to the target_function: . :param target_function: function :return:
597class ChainUniRunner: 598 def __init__(self, current_globals, chain, simple_mode=False, function_result_criteria=None): 599 self.current_globals = current_globals 600 self.chain = chain 601 self.simple_mode = simple_mode 602 self.default_function_result_criteria = function_result_criteria or (lambda result: True) 603 self.function_result_criteria = self.default_function_result_criteria 604 605 self.runner_class = _ChainRunner 606 if self.simple_mode: 607 self.runner_class = _ChainRunnerSimple 608 609 def set_function_result_criteria(self, result_criteria_computer): 610 self.function_result_criteria = result_criteria_computer 611 612 def reset_function_result_criteria(self): 613 self.function_result_criteria = self.default_function_result_criteria 614 615 def __call__(self, link_id=None, link_info=None, link_results_criteria=None, 616 ignore_link_result_criteria=None): 617 result = self.runner_class(self.current_globals, self.chain, link_id, link_info, 618 link_results_criteria, ignore_link_result_criteria, self.function_result_criteria) 619 return result
598 def __init__(self, current_globals, chain, simple_mode=False, function_result_criteria=None): 599 self.current_globals = current_globals 600 self.chain = chain 601 self.simple_mode = simple_mode 602 self.default_function_result_criteria = function_result_criteria or (lambda result: True) 603 self.function_result_criteria = self.default_function_result_criteria 604 605 self.runner_class = _ChainRunner 606 if self.simple_mode: 607 self.runner_class = _ChainRunnerSimple
646class ChainUniCallRunner: 647 def __init__(self, chain, simple_mode=False, function_result_criteria=None): 648 self.chain = chain 649 self.simple_mode = simple_mode 650 self.default_function_result_criteria = function_result_criteria or (lambda result: True) 651 self.function_result_criteria = self.default_function_result_criteria 652 653 self.runner_class = _ChainCallRunner 654 if self.simple_mode: 655 self.runner_class = _ChainCallRunnerSimple 656 657 def set_function_result_criteria(self, result_criteria_computer): 658 self.function_result_criteria = result_criteria_computer 659 660 def reset_function_result_criteria(self): 661 self.function_result_criteria = self.default_function_result_criteria 662 663 def __call__(self, link_id=None, link_info=None, link_results_criteria=None, 664 ignore_link_result_criteria=None): 665 result = self.runner_class(self.chain, link_id, link_info, 666 link_results_criteria, ignore_link_result_criteria, self.function_result_criteria) 667 return result
647 def __init__(self, chain, simple_mode=False, function_result_criteria=None): 648 self.chain = chain 649 self.simple_mode = simple_mode 650 self.default_function_result_criteria = function_result_criteria or (lambda result: True) 651 self.function_result_criteria = self.default_function_result_criteria 652 653 self.runner_class = _ChainCallRunner 654 if self.simple_mode: 655 self.runner_class = _ChainCallRunnerSimple
697class ChainValRunner: 698 def __init__(self, chain, function_result_criteria=None, reaction_to_the_result=None): 699 self.chain = chain 700 self.default_function_result_criteria = function_result_criteria or (lambda result: True) 701 self.function_result_criteria = self.default_function_result_criteria 702 self.reaction_to_the_result = reaction_to_the_result 703 704 def set_function_result_criteria(self, result_criteria_computer): 705 self.function_result_criteria = result_criteria_computer 706 707 def reset_function_result_criteria(self): 708 self.function_result_criteria = self.default_function_result_criteria 709 710 def __call__(self, link_id=None, link_info=None, link_results_criteria=None, 711 ignore_link_result_criteria=None): 712 result = _ChainValRunner(self.chain, link_id, link_info, 713 link_results_criteria, ignore_link_result_criteria, 714 self.function_result_criteria, self.reaction_to_the_result) 715 return result
698 def __init__(self, chain, function_result_criteria=None, reaction_to_the_result=None): 699 self.chain = chain 700 self.default_function_result_criteria = function_result_criteria or (lambda result: True) 701 self.function_result_criteria = self.default_function_result_criteria 702 self.reaction_to_the_result = reaction_to_the_result
718@contextmanager 719def chain_reader(chain, link_results_criteria=None, close=False): 720 if link_results_criteria is not None: 721 chain._push_criteria(link_results_criteria) 722 try: 723 yield chain 724 except: 725 raise 726 finally: 727 if link_results_criteria is not None: 728 chain._pop_criteria() 729 if close: 730 chain.close()
733def chain_reader__function(target_function): 734 """ 735 Parameters: chain__chain= (required), chain__link_results_criteria= (optional), chain__close= (optional). 736 Parameters passed to the target_function: chain__chain (after local link configuration). 737 :param target_function: function 738 :return: 739 """ 740 741 def new_target_function(*args, **kwargs): 742 chain = None 743 if 'chain__chain' in kwargs: 744 chain = kwargs['chain__chain'] 745 del kwargs['chain__chain'] 746 else: 747 raise ChainFunctionParameterNeeded('chain__chain') 748 749 link_results_criteria = None 750 if 'chain__link_results_criteria' in kwargs: 751 link_results_criteria = kwargs['chain__link_results_criteria'] 752 del kwargs['chain__link_results_criteria'] 753 754 close = None 755 if 'chain__close' in kwargs: 756 close = kwargs['chain__close'] 757 del kwargs['chain__close'] 758 759 target_function_result = None 760 with chain_reader(chain, link_results_criteria, close) as context: 761 kwargs['chain__chain'] = context 762 target_function_result = target_function(*args, **kwargs) 763 764 return target_function_result 765 766 return new_target_function
Parameters: chain__chain= (required), chain__link_results_criteria= (optional), chain__close= (optional). Parameters passed to the target_function: chain__chain (after local link configuration). :param target_function: function :return:
796class ChainReaderRunner: 797 def __init__(self, current_globals, chain): 798 self.current_globals = current_globals 799 self.chain = chain 800 801 def __call__(self, link_results_criteria=None, close=False): 802 result = _ChainReaderRunner(self.current_globals, self.chain, link_results_criteria, close) 803 return result