cengal.code_flow_control.chained_flow.versions.v_0.smart_chain

  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_0.result_types 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 IsOK_BlockFailed(Exception): pass
 45
 46
 47class IsOK_Closed(Exception):
 48    """
 49    is_ok considers it ordinary external exception
 50    """
 51    def __init__(self, context_holder, block_id, block_info):
 52        super(IsOK_Closed, self).__init__('Content Holder is closed. '
 53                                          'Content Holder ID: {}; '
 54                                          'Content Holder Info: {}; '
 55                                          'Block ID: {}; '
 56                                          'Block Info {}'.format(str(context_holder._context_holder_id),
 57                                                                 str(context_holder._context_holder_info),
 58                                                                 str(block_id),
 59                                                                 str(block_info)))
 60        self.context_holder = context_holder
 61        self.block_id = block_id
 62        self.block_info = block_info
 63
 64
 65class IsOKForFunction_ParameterNeeded(Exception): pass
 66
 67
 68class CriteriaType(Enum):
 69# class CriteriaType():  # much more efficient than Enum inheritance
 70    needed = 0  # only set of this blocks is needed (should be already successfully done)
 71    optional = 1  # all blocks are needed except of this set of blocks
 72    any = 2  # any result will fit criteria
 73    forbidden = 3  # set of this blocks should be already failed
 74    not_successful = 4  # set of this blocks should not be successfully done (also may not start) at the check time
 75
 76
 77class IgnoreBlockResultCriteriaType(Enum):
 78    do_not_ignore = 0
 79    ignore_if_failed = 1
 80    ignore_if_successful = 2
 81
 82
 83class IsOK_HistoryExport(Exception):
 84    def __init__(self, history, process_error_result=True):
 85        super(IsOK_HistoryExport, self).__init__('')
 86        self.history = history
 87        self.process_error_result = process_error_result
 88
 89
 90class IsOK_IntenalResult:
 91    def __init__(self, type_id, str_data, data):
 92        self.type_id = type_id
 93        self.str_data = str_data
 94        self.data = data
 95
 96    def __str__(self):
 97        return self.str_data
 98
 99
100class IsOK_IntenalResultType(Enum):
101# class CriteriaType():  # much more efficient than Enum inheritance
102    built_in_exception__is_ok_block_failed = 0
103    built_in_exception__bad_history_import = 1
104    external_exception = 2
105    block_did_not_returned_an_answer = 3
106
107
108class IsOK_ContextHolder:
109    def __init__(self, context_holder_id=None, context_holder_info=None, global_block_results_criteria=None,
110                 raise_exceptions=False, save_debug_trace=False, closeable=True):
111        """
112
113        :param context_holder_id:
114        :param context_holder_info:
115        :param global_block_results_criteria: will be set to ResultType(CriteriaType.optional, set()) if None;
116            in this case all blocks are required.
117        :param raise_exceptions:
118        :param save_debug_trace:
119        :param closeable:
120        :return:
121        """
122        # Use only ResultType(CriteriaType.optional, ...) or ResultType(CriteriaType.needed, set()).
123        # Other will be ignored here.
124        # You may use global_block_results_criteria=ResultType(CriteriaType.optional, set()) to create criteria
125        # "no fails in any block"
126        self._context_holder_id = context_holder_id
127        self._context_holder_info = context_holder_info
128        self._internal_blocks_index = IDGenerator()
129        self._reserve_block_id_generator = IDGenerator(GeneratorType.guid_string)
130        self._criteria_list = list()
131        global_block_results_criteria = global_block_results_criteria or ResultType(CriteriaType.optional, set())
132        if global_block_results_criteria is not None:
133            self._criteria_list.append(global_block_results_criteria)
134        self._raise_exceptions = raise_exceptions
135        self._save_debug_trace = save_debug_trace
136        self._closeable = closeable
137        self._full_history = list()
138        self._blocks_library = dict()
139        self._all_made_blocks = set()
140        self._good_blocks = set()
141        self._bad_blocks = set()
142
143        self._current_block_id = None
144        self._current_block_info = None
145        self._current_block_result = None
146        self._closed = False
147
148        self._bool_result = ResultCache()
149
150    # def _push_criteria(self, set_of_needed_blocks=None, set_of_optional_blocks=None):
151    def _push_criteria(self, block_results_criteria):
152        # Do not use!
153        self._bool_result()
154        self._criteria_list.append(block_results_criteria)
155
156    def _pop_criteria(self):
157        # Do not use!
158        # May raise exception if len(self.criteria_list)==0, but this is OK.
159        self._bool_result()
160        return self._criteria_list.pop()
161
162    def read_criteria(self):
163        criteria = None
164        if self._criteria_list:
165            criteria = self._criteria_list[-1]
166        return criteria
167
168    def _push_block_info(self, block_id, block_info=None):
169        self._current_block_id = block_id
170        self._current_block_info = block_info
171        self._current_block_result = None
172
173    def _pop_block_info(self):
174        self._current_block_id = None
175        self._current_block_info = None
176        self._current_block_result = None
177
178    def push_result(self, bool_result, info_or_data=None):
179        self._current_block_result = (bool_result, info_or_data)
180
181    def push_result_c(self, result):
182        # "class" version: to use when result = ResultExistence()
183        self._current_block_result = (result.existence, result.result)
184
185    def read_block_result_link(self, block_id):
186        # result is NOT protected from changing!
187        original_result_data = self._blocks_library[block_id][3]
188        result = ResultExistence(original_result_data[0], original_result_data[1])
189        # result = self._blocks_library[block_id][3]
190        return result
191
192    def read_block_result_copy(self, block_id):
193        original_result_data = self._blocks_library[block_id][3]
194        result = ResultExistence(original_result_data[0], copy.copy(original_result_data[1]))
195        return result
196
197    def read_block_result_deepcopy(self, block_id):
198        original_result_data = self._blocks_library[block_id][3]
199        result = ResultExistence(original_result_data[0], copy.deepcopy(original_result_data[1]))
200        return result
201
202    def _save_block_result(self, ignore_block_result_criteria=None):
203        # ignore_block_result_criteria = ignore_block_result_criteria or IgnoreBlockResultCriteriaType.do_not_ignore
204        if ((IgnoreBlockResultCriteriaType.ignore_if_failed == ignore_block_result_criteria) and
205                (not self._current_block_result[0])) \
206                or ((IgnoreBlockResultCriteriaType.ignore_if_successful == ignore_block_result_criteria) and
207                        self._current_block_result[0]):
208            return
209
210        self._bool_result()
211        import_depth = 0
212        full_block_info = (self._internal_blocks_index(), self._current_block_id, self._current_block_info,
213                           self._current_block_result, import_depth)
214        self._full_history.append(full_block_info)
215        self._blocks_library[self._current_block_id] = full_block_info
216        self._all_made_blocks.add(self._current_block_id)
217        if self._current_block_result[0]:
218            self._good_blocks.add(self._current_block_id)
219        else:
220            self._bad_blocks.add(self._current_block_id)
221
222    def __bool__(self):
223        if self._bool_result:
224            return self._bool_result.get()
225        else:
226            current_criteria = self.read_criteria()
227            result = True
228            if CriteriaType.needed == current_criteria:
229                if len(current_criteria.result) != len(current_criteria.result & self._good_blocks):
230                    result = False
231            elif CriteriaType.optional == current_criteria:
232                if len(self._bad_blocks - current_criteria.result) != 0:
233                    result = False
234            elif CriteriaType.any == current_criteria:
235                result = True
236            elif CriteriaType.forbidden == current_criteria:
237                if len(current_criteria.result) != len(current_criteria.result & self._bad_blocks):
238                    result = False
239            elif CriteriaType.not_successful == current_criteria:
240                if len(current_criteria.result & self._good_blocks) != 0:
241                    result = False
242            self._bool_result.set(result)
243            return result
244
245    def __nonzero__(self):
246        return self.__bool__()
247
248    @staticmethod
249    def _block_list_to_str(block_list):
250        blocks_str = ',\n'.join('(index({}), depth({}), ID({}), INFO({}), RESULT({}))'.format(str(block[0]),
251                                                                                              str(block[4]),
252                                                                                              str(block[1]),
253                                                                                              str(block[2]),
254                                                          '({}, {})'.format(str(block[3][0]), str(block[3][1])))
255                                for block in block_list)
256        return blocks_str
257
258    def _block_str_to_context_holder_str(self, blocks_str):
259        full_string = '{{{{CONTEXT_HOLDER_ID({}): CONTEXT_HOLDER_INFO({})}}:[\n{}\n]}}'.format(
260            self._context_holder_id, self._context_holder_info, blocks_str)
261        return full_string
262
263    def get_bad_blocks(self):
264        result = list()
265        for block in self._full_history:
266            if not block[3][0]:
267                result.append(block)
268        return result
269
270    def get_bad_blocks_str(self):
271        bad_blocks = self.get_bad_blocks()
272        full_history_str = self._block_list_to_str(bad_blocks)
273        full_string = self._block_str_to_context_holder_str(full_history_str)
274        return full_string
275
276    def raise_bad_blocks(self):
277        raise IsOK_HistoryExport(self.get_bad_blocks())
278
279    def raise_full_history(self):
280        raise IsOK_HistoryExport(self._full_history)
281
282    def process_history_import(self, his_ex):
283        history = his_ex.history
284        for block in history:
285            full_block_info = (self._internal_blocks_index.get_new_ID(), block[1], block[2],
286                               block[3], block[4] + 1)
287            self._full_history.append(full_block_info)
288
289    def close(self):
290        self._closed = True
291
292    def _reopen(self):
293        self._closed = False
294
295    def __str__(self):
296        full_history_str = self._block_list_to_str(self._full_history)
297        full_string = self._block_str_to_context_holder_str(full_history_str)
298        return full_string
299
300    def __call__(self, *args, **kwargs):
301        return is_ok(self, *args, **kwargs)
302
303    def is_ok(self, *args, **kwargs):
304        return self.__call__(*args, **kwargs)
305
306
307@contextmanager
308def is_ok(context_holder, block_id, block_info=None, block_results_criteria=None, ignore_block_result_criteria=None):
309    if block_id is None:
310        new_id = context_holder._reserve_block_id_generator()
311        block_id = (new_id, new_id)
312
313    if context_holder._closeable and context_holder._closed:
314        raise IsOK_Closed(context_holder, block_id, block_info)
315
316    context_holder._push_block_info(block_id, block_info)
317    if block_results_criteria is not None:
318        context_holder._push_criteria(block_results_criteria)
319    need_to_save_block_result = True
320    try:
321        yield context_holder
322    except IsOK_BlockFailed as exc:
323        result_info = None
324        if exc.args:
325            result_info = exc.args[0]
326        context_holder.push_result(False, IsOK_IntenalResult(
327                IsOK_IntenalResultType.built_in_exception__is_ok_block_failed,
328                'ISOK INTERNAL RESULT. BUILT-IN EXCEPTION: IsOK_BlockFailed ({})'.format(result_info), result_info))
329    except IsOK_HistoryExport as export:
330        context_holder.process_history_import(export)
331        if export.process_error_result:
332            context_holder.push_result(False, IsOK_IntenalResult(
333                    IsOK_IntenalResultType.built_in_exception__bad_history_import,
334                    'ISOK INTERNAL RESULT. BUILT-IN EXCEPTION: BAD HISTORY IMPORT EXCEPTION', None))
335    except:
336        exc = sys.exc_info()
337        exc_type, exc_obj, exc_tb = exc
338        tb_full_file_name = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
339        tb_line_number = exc_tb.tb_lineno
340        tb_function_name = str()
341        tb_text = str()
342
343        tb_list = traceback.extract_tb(exc_tb, 2)
344        if len(tb_list) >= 2:
345            actual_tb = tb_list[1]
346            tb_full_file_name, tb_line_number, tb_function_name, tb_text = actual_tb
347
348        exception = exc
349        error_str = '{} {}'.format(str(exception[0]), str(exception[1].args[0]))
350        # print('+++', error_str)
351        formatted_traceback = traceback.format_exception(exception[0], exception[1], exception[2])
352        exception = exception[:2] + (formatted_traceback,)
353        trace_str = ''.join(exception[2])
354        if context_holder._save_debug_trace:
355            result_string = 'ISOK INTERNAL RESULT. CODE EXCEPTION "{}" AT "{}":{} in {} WITH TRACE: \n' \
356                            '{}\n' \
357                            '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~' \
358                            ''.format(error_str, tb_full_file_name, tb_line_number, tb_function_name, trace_str)
359        else:
360            result_string = 'ISOK INTERNAL RESULT. CODE EXCEPTION "{}" AT "{}":{} in {}'.format(
361                    error_str, tb_full_file_name, tb_line_number, tb_function_name)
362        context_holder.push_result(False, IsOK_IntenalResult(
363                IsOK_IntenalResultType.external_exception, result_string, exc))
364        # print(result_string)
365        # _is_ok_reader_runner__context_holder.push_result(False, sys.exc_info()[1])
366        if context_holder._raise_exceptions:
367            need_to_save_block_result = False
368            context_holder._save_block_result()
369            context_holder.raise_bad_blocks()
370            # raise
371    else:
372        if context_holder._current_block_result is None:
373            # _is_ok_reader_runner__context_holder.push_result(True)
374            context_holder.push_result(False, IsOK_IntenalResult(
375                    IsOK_IntenalResultType.block_did_not_returned_an_answer,
376                    'ISOK INTERNAL RESULT. BLOCK DID NOT RETURN RESULT', None))
377    finally:
378        if need_to_save_block_result:
379            context_holder._save_block_result(ignore_block_result_criteria)
380        if block_results_criteria is not None:
381            context_holder._pop_criteria()
382        context_holder._pop_block_info()
383
384
385def is_ok__function(target_function):
386    """
387    Parameters: is_ok__context_holder= (required)
388        , is_ok__block_id= (required)
389        , is_ok__block_info= (optional)
390        , is_ok__block_results_criteria= (optional)
391        , is_ok__ignore_block_result_criteria= (optional).
392    Parameters passed to the target_function: is_ok__context_holder (after local block configuration).
393    :param target_function: function
394    :return:
395    """
396    def new_target_function(*args, **kwargs):
397        context_holder = None
398        if 'is_ok__context_holder' in kwargs:
399            context_holder = kwargs['is_ok__context_holder']
400            del kwargs['is_ok__context_holder']
401        else:
402            raise IsOKForFunction_ParameterNeeded('is_ok__context_holder')
403
404        block_id = None
405        if 'is_ok__block_id' in kwargs:
406            block_id = kwargs['is_ok__block_id']
407            del kwargs['is_ok__block_id']
408        else:
409            raise IsOKForFunction_ParameterNeeded('is_ok__block_id')
410
411        block_info = None
412        if 'is_ok__block_info' in kwargs:
413            block_info = kwargs['is_ok__block_info']
414            del kwargs['is_ok__block_info']
415
416        block_results_criteria = None
417        if 'is_ok__block_results_criteria' in kwargs:
418            block_results_criteria = kwargs['is_ok__block_results_criteria']
419            del kwargs['is_ok__block_results_criteria']
420
421        ignore_block_result_criteria = None
422        if 'is_ok__ignore_block_result_criteria' in kwargs:
423            ignore_block_result_criteria = kwargs['is_ok__ignore_block_result_criteria']
424            del kwargs['is_ok__ignore_block_result_criteria']
425
426        target_function_result = None
427        with is_ok(context_holder, block_id, block_info, block_results_criteria, ignore_block_result_criteria) as \
428                context:
429            kwargs['is_ok__context_holder'] = context
430            target_function_result = target_function(*args, **kwargs)
431
432        return target_function_result
433
434    return new_target_function
435
436
437class _IsOkRunner:
438    def __init__(self, current_globals, context_holder, block_id=None, block_info=None, block_results_criteria=None,
439                 ignore_block_result_criteria=None, function_result_criteria=None):
440        self._is_ok_runner__current_globals = current_globals
441        self._is_ok_runner__context_holder = context_holder
442        self._is_ok_runner__block_id = block_id
443        self._is_ok_runner__block_info = block_info
444        self._is_ok_runner__block_results_criteria = block_results_criteria
445        self._is_ok_runner__ignore_block_result_criteria = ignore_block_result_criteria
446
447    def __getattr__(self, name):
448        target_functor = None
449        if name in self._is_ok_runner__current_globals:
450            target_functor = self._is_ok_runner__current_globals[name]
451        else:
452            raise AttributeError(name)
453
454        def new_target_function(*args, **kwargs):
455            target_function_result = None
456            block_id = self._is_ok_runner__block_id or str(target_functor)
457            with is_ok(self._is_ok_runner__context_holder, block_id, self._is_ok_runner__block_info,
458                       self._is_ok_runner__block_results_criteria,
459                       self._is_ok_runner__ignore_block_result_criteria) as context:
460                kwargs['is_ok__context_holder'] = context
461                target_function_result = target_functor(*args, **kwargs)
462
463            return target_function_result
464
465        return new_target_function
466
467
468class IsOkRunner:
469    def __init__(self, current_globals, context_holder):
470        self.current_globals = current_globals
471        self.context_holder = context_holder
472
473    def __call__(self, block_id=None, block_info=None, block_results_criteria=None,
474                 ignore_block_result_criteria=None):
475        result = _IsOkRunner(self.current_globals, self.context_holder, block_id, block_info, block_results_criteria,
476                             ignore_block_result_criteria)
477        return result
478
479
480class _IsOkCallRunner:
481    def __init__(self, context_holder, block_id=None, block_info=None, block_results_criteria=None,
482                 ignore_block_result_criteria=None, function_result_criteria=None):
483        self._is_ok_runner__context_holder = context_holder
484        self._is_ok_runner__block_id = block_id
485        self._is_ok_runner__block_info = block_info
486        self._is_ok_runner__block_results_criteria = block_results_criteria
487        self._is_ok_runner__ignore_block_result_criteria = ignore_block_result_criteria
488
489    def __call__(self, target_functor, *args, **kwargs):
490        target_function_result = None
491        block_id = self._is_ok_runner__block_id or str(target_functor)
492        with is_ok(self._is_ok_runner__context_holder, block_id, self._is_ok_runner__block_info,
493                   self._is_ok_runner__block_results_criteria,
494                   self._is_ok_runner__ignore_block_result_criteria) as context:
495            kwargs['is_ok__context_holder'] = context
496            target_function_result = target_functor(*args, **kwargs)
497
498        return target_function_result
499
500
501class IsOkCallRunner:
502    def __init__(self, context_holder):
503        self.context_holder = context_holder
504
505    def __call__(self, block_id=None, block_info=None, block_results_criteria=None,
506                 ignore_block_result_criteria=None):
507        result = _IsOkCallRunner(self.context_holder, block_id, block_info, block_results_criteria,
508                                 ignore_block_result_criteria)
509        return result
510
511
512def is_ok__function__simple(target_function):
513    """
514    Parameters: is_ok__context_holder= (required)
515        , is_ok__block_id= (optional) (default value == str(target_function))
516        , is_ok__block_results_criteria= (optional)
517        , is_ok__ignore_block_result_criteria= (optional).
518    Parameters passed to the target_function: .
519    :param target_function: function
520    :return:
521    """
522    def new_target_function(*args, **kwargs):
523        context_holder = None
524        if 'is_ok__context_holder' in kwargs:
525            context_holder = kwargs['is_ok__context_holder']
526            del kwargs['is_ok__context_holder']
527        else:
528            raise IsOKForFunction_ParameterNeeded('is_ok__context_holder')
529
530        # block_id = '__UNNAMED_FUNCTION_SIMPLE_BLOCK__'
531        block_id = str(target_function)
532        if 'is_ok__block_id' in kwargs:
533            block_id = kwargs['is_ok__block_id']
534            del kwargs['is_ok__block_id']
535
536        block_results_criteria = None
537        if 'is_ok__block_results_criteria' in kwargs:
538            block_results_criteria = kwargs['is_ok__block_results_criteria']
539            del kwargs['is_ok__block_results_criteria']
540
541        ignore_block_result_criteria = None
542        if 'is_ok__ignore_block_result_criteria' in kwargs:
543            ignore_block_result_criteria = kwargs['is_ok__ignore_block_result_criteria']
544            del kwargs['is_ok__ignore_block_result_criteria']
545
546        target_function_result = None
547        with is_ok(context_holder, block_id, None, block_results_criteria, ignore_block_result_criteria) as context:
548            if context:
549                target_function_result = target_function(*args, **kwargs)
550                context.push_result(True, target_function_result)
551
552        return target_function_result
553
554    return new_target_function
555
556
557class _IsOkRunnerSimple:
558    def __init__(self, current_globals, context_holder, block_id=None, block_info=None, block_results_criteria=None,
559                 ignore_block_result_criteria=None, function_result_criteria=None):
560        self._is_ok_runner_simple__current_globals = current_globals
561        self._is_ok_runner_simple__context_holder = context_holder
562        self._is_ok_runner_simple__block_id = block_id
563        self._is_ok_runner_simple__block_info = block_info
564        self._is_ok_runner_simple__block_results_criteria = block_results_criteria
565        self._is_ok_runner_simple__ignore_block_result_criteria = ignore_block_result_criteria
566        self._is_ok_runner_simple__function_result_criteria = function_result_criteria or (lambda result: True)
567
568    def __getattr__(self, name):
569        target_functor = None
570        if name in self._is_ok_runner_simple__current_globals:
571            target_functor = self._is_ok_runner_simple__current_globals[name]
572        else:
573            raise AttributeError(name)
574
575        def new_target_function(*args, **kwargs):
576            target_function_result = None
577            block_id = self._is_ok_runner_simple__block_id or str(target_functor)
578            with is_ok(self._is_ok_runner_simple__context_holder, block_id, self._is_ok_runner_simple__block_info,
579                       self._is_ok_runner_simple__block_results_criteria,
580                       self._is_ok_runner_simple__ignore_block_result_criteria) as context:
581                if context:
582                    target_function_result = target_functor(*args, **kwargs)
583                    is_good_result = self._is_ok_runner_simple__function_result_criteria(target_function_result)
584                    context.push_result(is_good_result, target_function_result)
585
586            return target_function_result
587
588        return new_target_function
589
590
591class IsOkUniRunner:
592    def __init__(self, current_globals, context_holder, simple_mode=False, function_result_criteria=None):
593        self.current_globals = current_globals
594        self.context_holder = context_holder
595        self.simple_mode = simple_mode
596        self.default_function_result_criteria = function_result_criteria or (lambda result: True)
597        self.function_result_criteria = self.default_function_result_criteria
598
599        self.runner_class = _IsOkRunner
600        if self.simple_mode:
601            self.runner_class = _IsOkRunnerSimple
602
603    def set_function_result_criteria(self, result_criteria_computer):
604        self.function_result_criteria = result_criteria_computer
605
606    def reset_function_result_criteria(self):
607        self.function_result_criteria = self.default_function_result_criteria
608
609    def __call__(self, block_id=None, block_info=None, block_results_criteria=None,
610                 ignore_block_result_criteria=None):
611        result = self.runner_class(self.current_globals, self.context_holder, block_id, block_info,
612                                   block_results_criteria, ignore_block_result_criteria, self.function_result_criteria)
613        return result
614
615
616class _IsOkCallRunnerSimple:
617    def __init__(self, context_holder, block_id=None, block_info=None, block_results_criteria=None,
618                 ignore_block_result_criteria=None, function_result_criteria=None):
619        self._is_ok_runner_simple__context_holder = context_holder
620        self._is_ok_runner_simple__block_id = block_id
621        self._is_ok_runner_simple__block_info = block_info
622        self._is_ok_runner_simple__block_results_criteria = block_results_criteria
623        self._is_ok_runner_simple__ignore_block_result_criteria = ignore_block_result_criteria
624        self._is_ok_runner_simple__function_result_criteria = function_result_criteria or (lambda result: True)
625
626    def __call__(self, target_functor, *args, **kwargs):
627        target_function_result = None
628        block_id = self._is_ok_runner_simple__block_id or str(target_functor)
629        with is_ok(self._is_ok_runner_simple__context_holder, block_id, self._is_ok_runner_simple__block_info,
630                   self._is_ok_runner_simple__block_results_criteria,
631                   self._is_ok_runner_simple__ignore_block_result_criteria) as context:
632            if context:
633                target_function_result = target_functor(*args, **kwargs)
634                is_good_result = self._is_ok_runner_simple__function_result_criteria(target_function_result)
635                context.push_result(is_good_result, target_function_result)
636
637        return target_function_result
638
639
640class IsOkUniCallRunner:
641    def __init__(self, context_holder, simple_mode=False, function_result_criteria=None):
642        self.context_holder = context_holder
643        self.simple_mode = simple_mode
644        self.default_function_result_criteria = function_result_criteria or (lambda result: True)
645        self.function_result_criteria = self.default_function_result_criteria
646
647        self.runner_class = _IsOkCallRunner
648        if self.simple_mode:
649            self.runner_class = _IsOkCallRunnerSimple
650
651    def set_function_result_criteria(self, result_criteria_computer):
652        self.function_result_criteria = result_criteria_computer
653
654    def reset_function_result_criteria(self):
655        self.function_result_criteria = self.default_function_result_criteria
656
657    def __call__(self, block_id=None, block_info=None, block_results_criteria=None,
658                 ignore_block_result_criteria=None):
659        result = self.runner_class(self.context_holder, block_id, block_info,
660                                   block_results_criteria, ignore_block_result_criteria, self.function_result_criteria)
661        return result
662
663
664class _IsOkValRunner:
665    def __init__(self, context_holder, block_id=None, block_info=None, block_results_criteria=None,
666                 ignore_block_result_criteria=None, function_result_criteria=None, reaction_to_the_result=None):
667        self._is_ok_runner_simple__context_holder = context_holder
668        self._is_ok_runner_simple__block_id = block_id
669        self._is_ok_runner_simple__block_info = block_info
670        self._is_ok_runner_simple__block_results_criteria = block_results_criteria
671        self._is_ok_runner_simple__ignore_block_result_criteria = ignore_block_result_criteria
672        self._is_ok_runner_simple__function_result_criteria = function_result_criteria or (lambda result: True)
673        self._is_ok_runner_simple__reaction_to_the_result = reaction_to_the_result
674
675    def __call__(self, functor_result):
676        target_function_result = functor_result
677        block_id = self._is_ok_runner_simple__block_id
678        with is_ok(self._is_ok_runner_simple__context_holder, block_id, self._is_ok_runner_simple__block_info,
679                   self._is_ok_runner_simple__block_results_criteria,
680                   self._is_ok_runner_simple__ignore_block_result_criteria) as context:
681            if context:
682                is_good_result = self._is_ok_runner_simple__function_result_criteria(target_function_result)
683                if self._is_ok_runner_simple__reaction_to_the_result is not None:
684                    verdict = self._is_ok_runner_simple__reaction_to_the_result(is_good_result, target_function_result)
685                    target_function_result = (target_function_result, verdict)
686                context.push_result(is_good_result, target_function_result)
687
688        return functor_result
689
690
691class IsOkValRunner:
692    def __init__(self, context_holder, function_result_criteria=None, reaction_to_the_result=None):
693        self.context_holder = context_holder
694        self.default_function_result_criteria = function_result_criteria or (lambda result: True)
695        self.function_result_criteria = self.default_function_result_criteria
696        self.reaction_to_the_result = reaction_to_the_result
697
698    def set_function_result_criteria(self, result_criteria_computer):
699        self.function_result_criteria = result_criteria_computer
700
701    def reset_function_result_criteria(self):
702        self.function_result_criteria = self.default_function_result_criteria
703
704    def __call__(self, block_id=None, block_info=None, block_results_criteria=None,
705                 ignore_block_result_criteria=None):
706        result = _IsOkValRunner(self.context_holder, block_id, block_info,
707                                block_results_criteria, ignore_block_result_criteria,
708                                self.function_result_criteria, self.reaction_to_the_result)
709        return result
710
711
712@contextmanager
713def is_ok_reader(context_holder, block_results_criteria=None, close=False):
714    if block_results_criteria is not None:
715        context_holder._push_criteria(block_results_criteria)
716    try:
717        yield context_holder
718    except:
719        raise
720    finally:
721        if block_results_criteria is not None:
722            context_holder._pop_criteria()
723        if close:
724            context_holder.close()
725
726
727def is_ok_reader__function(target_function):
728    """
729    Parameters: is_ok__context_holder= (required), is_ok__block_results_criteria= (optional), is_ok__close= (optional).
730    Parameters passed to the target_function: is_ok__context_holder (after local block configuration).
731    :param target_function: function
732    :return:
733    """
734    def new_target_function(*args, **kwargs):
735        context_holder = None
736        if 'is_ok__context_holder' in kwargs:
737            context_holder = kwargs['is_ok__context_holder']
738            del kwargs['is_ok__context_holder']
739        else:
740            raise IsOKForFunction_ParameterNeeded('is_ok__context_holder')
741
742        block_results_criteria = None
743        if 'is_ok__block_results_criteria' in kwargs:
744            block_results_criteria = kwargs['is_ok__block_results_criteria']
745            del kwargs['is_ok__block_results_criteria']
746
747        close = None
748        if 'is_ok__close' in kwargs:
749            close = kwargs['is_ok__close']
750            del kwargs['is_ok__close']
751
752        target_function_result = None
753        with is_ok_reader(context_holder, block_results_criteria, close) as context:
754            kwargs['is_ok__context_holder'] = context
755            target_function_result = target_function(*args, **kwargs)
756
757        return target_function_result
758
759    return new_target_function
760
761
762class _IsOkReaderRunner:
763    def __init__(self, current_globals, context_holder, block_results_criteria=None, close=False):
764        self._is_ok_reader_runner__current_globals = current_globals
765        self._is_ok_reader_runner__context_holder = context_holder
766        self._is_ok_reader_runner__block_results_criteria = block_results_criteria
767        self._is_ok_reader_runner__close = close
768
769    def __getattr__(self, name):
770        target_functor = None
771        if name in self._is_ok_reader_runner__current_globals:
772            target_functor = self._is_ok_reader_runner__current_globals[name]
773        else:
774            raise AttributeError(name)
775
776        def new_target_function(*args, **kwargs):
777            target_function_result = None
778            with is_ok_reader(self._is_ok_reader_runner__context_holder,
779                              self._is_ok_reader_runner__block_results_criteria,
780                              self._is_ok_reader_runner__close) as context:
781                kwargs['is_ok__context_holder'] = context
782                target_function_result = target_functor(*args, **kwargs)
783
784            return target_function_result
785
786        return new_target_function
787
788
789class IsOkReaderRunner:
790    def __init__(self, current_globals, context_holder):
791        self.current_globals = current_globals
792        self.context_holder = context_holder
793
794    def __call__(self, block_results_criteria=None, close=False):
795        result = _IsOkReaderRunner(self.current_globals, self.context_holder, block_results_criteria, close)
796        return result
797
798
799class _IsOkReaderCallRunner:
800    def __init__(self, context_holder, block_results_criteria=None, close=False):
801        self._is_ok_reader_runner__context_holder = context_holder
802        self._is_ok_reader_runner__block_results_criteria = block_results_criteria
803        self._is_ok_reader_runner__close = close
804
805    def __call__(self, target_functor, *args, **kwargs):
806        target_function_result = None
807        with is_ok_reader(self._is_ok_reader_runner__context_holder,
808                          self._is_ok_reader_runner__block_results_criteria,
809                          self._is_ok_reader_runner__close) as context:
810            kwargs['is_ok__context_holder'] = context
811            target_function_result = target_functor(*args, **kwargs)
812
813        return target_function_result
814
815
816class IsOkReaderCallRunner:
817    def __init__(self, context_holder):
818        self.context_holder = context_holder
819
820    def __call__(self, block_results_criteria=None, close=False):
821        result = _IsOkReaderCallRunner(self.context_holder, block_results_criteria, close)
822        return result
class IsOK_BlockFailed(builtins.Exception):
45class IsOK_BlockFailed(Exception): pass

Common base class for all non-exit exceptions.

Inherited Members
builtins.Exception
Exception
builtins.BaseException
with_traceback
args
class IsOK_Closed(builtins.Exception):
48class IsOK_Closed(Exception):
49    """
50    is_ok considers it ordinary external exception
51    """
52    def __init__(self, context_holder, block_id, block_info):
53        super(IsOK_Closed, self).__init__('Content Holder is closed. '
54                                          'Content Holder ID: {}; '
55                                          'Content Holder Info: {}; '
56                                          'Block ID: {}; '
57                                          'Block Info {}'.format(str(context_holder._context_holder_id),
58                                                                 str(context_holder._context_holder_info),
59                                                                 str(block_id),
60                                                                 str(block_info)))
61        self.context_holder = context_holder
62        self.block_id = block_id
63        self.block_info = block_info

is_ok considers it ordinary external exception

IsOK_Closed(context_holder, block_id, block_info)
52    def __init__(self, context_holder, block_id, block_info):
53        super(IsOK_Closed, self).__init__('Content Holder is closed. '
54                                          'Content Holder ID: {}; '
55                                          'Content Holder Info: {}; '
56                                          'Block ID: {}; '
57                                          'Block Info {}'.format(str(context_holder._context_holder_id),
58                                                                 str(context_holder._context_holder_info),
59                                                                 str(block_id),
60                                                                 str(block_info)))
61        self.context_holder = context_holder
62        self.block_id = block_id
63        self.block_info = block_info
context_holder
block_id
block_info
Inherited Members
builtins.BaseException
with_traceback
args
class IsOKForFunction_ParameterNeeded(builtins.Exception):
66class IsOKForFunction_ParameterNeeded(Exception): pass

Common base class for all non-exit exceptions.

Inherited Members
builtins.Exception
Exception
builtins.BaseException
with_traceback
args
class CriteriaType(enum.Enum):
69class CriteriaType(Enum):
70# class CriteriaType():  # much more efficient than Enum inheritance
71    needed = 0  # only set of this blocks is needed (should be already successfully done)
72    optional = 1  # all blocks are needed except of this set of blocks
73    any = 2  # any result will fit criteria
74    forbidden = 3  # set of this blocks should be already failed
75    not_successful = 4  # set of this blocks should not be successfully done (also may not start) at the check time

An enumeration.

needed = <CriteriaType.needed: 0>
optional = <CriteriaType.optional: 1>
any = <CriteriaType.any: 2>
forbidden = <CriteriaType.forbidden: 3>
not_successful = <CriteriaType.not_successful: 4>
Inherited Members
enum.Enum
name
value
class IgnoreBlockResultCriteriaType(enum.Enum):
78class IgnoreBlockResultCriteriaType(Enum):
79    do_not_ignore = 0
80    ignore_if_failed = 1
81    ignore_if_successful = 2

An enumeration.

Inherited Members
enum.Enum
name
value
class IsOK_HistoryExport(builtins.Exception):
84class IsOK_HistoryExport(Exception):
85    def __init__(self, history, process_error_result=True):
86        super(IsOK_HistoryExport, self).__init__('')
87        self.history = history
88        self.process_error_result = process_error_result

Common base class for all non-exit exceptions.

IsOK_HistoryExport(history, process_error_result=True)
85    def __init__(self, history, process_error_result=True):
86        super(IsOK_HistoryExport, self).__init__('')
87        self.history = history
88        self.process_error_result = process_error_result
history
process_error_result
Inherited Members
builtins.BaseException
with_traceback
args
class IsOK_IntenalResult:
91class IsOK_IntenalResult:
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
IsOK_IntenalResult(type_id, str_data, data)
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
type_id
str_data
data
class IsOK_IntenalResultType(enum.Enum):
101class IsOK_IntenalResultType(Enum):
102# class CriteriaType():  # much more efficient than Enum inheritance
103    built_in_exception__is_ok_block_failed = 0
104    built_in_exception__bad_history_import = 1
105    external_exception = 2
106    block_did_not_returned_an_answer = 3

An enumeration.

built_in_exception__is_ok_block_failed = <IsOK_IntenalResultType.built_in_exception__is_ok_block_failed: 0>
built_in_exception__bad_history_import = <IsOK_IntenalResultType.built_in_exception__bad_history_import: 1>
external_exception = <IsOK_IntenalResultType.external_exception: 2>
block_did_not_returned_an_answer = <IsOK_IntenalResultType.block_did_not_returned_an_answer: 3>
Inherited Members
enum.Enum
name
value
class IsOK_ContextHolder:
109class IsOK_ContextHolder:
110    def __init__(self, context_holder_id=None, context_holder_info=None, global_block_results_criteria=None,
111                 raise_exceptions=False, save_debug_trace=False, closeable=True):
112        """
113
114        :param context_holder_id:
115        :param context_holder_info:
116        :param global_block_results_criteria: will be set to ResultType(CriteriaType.optional, set()) if None;
117            in this case all blocks are required.
118        :param raise_exceptions:
119        :param save_debug_trace:
120        :param closeable:
121        :return:
122        """
123        # Use only ResultType(CriteriaType.optional, ...) or ResultType(CriteriaType.needed, set()).
124        # Other will be ignored here.
125        # You may use global_block_results_criteria=ResultType(CriteriaType.optional, set()) to create criteria
126        # "no fails in any block"
127        self._context_holder_id = context_holder_id
128        self._context_holder_info = context_holder_info
129        self._internal_blocks_index = IDGenerator()
130        self._reserve_block_id_generator = IDGenerator(GeneratorType.guid_string)
131        self._criteria_list = list()
132        global_block_results_criteria = global_block_results_criteria or ResultType(CriteriaType.optional, set())
133        if global_block_results_criteria is not None:
134            self._criteria_list.append(global_block_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._blocks_library = dict()
140        self._all_made_blocks = set()
141        self._good_blocks = set()
142        self._bad_blocks = set()
143
144        self._current_block_id = None
145        self._current_block_info = None
146        self._current_block_result = None
147        self._closed = False
148
149        self._bool_result = ResultCache()
150
151    # def _push_criteria(self, set_of_needed_blocks=None, set_of_optional_blocks=None):
152    def _push_criteria(self, block_results_criteria):
153        # Do not use!
154        self._bool_result()
155        self._criteria_list.append(block_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_block_info(self, block_id, block_info=None):
170        self._current_block_id = block_id
171        self._current_block_info = block_info
172        self._current_block_result = None
173
174    def _pop_block_info(self):
175        self._current_block_id = None
176        self._current_block_info = None
177        self._current_block_result = None
178
179    def push_result(self, bool_result, info_or_data=None):
180        self._current_block_result = (bool_result, info_or_data)
181
182    def push_result_c(self, result):
183        # "class" version: to use when result = ResultExistence()
184        self._current_block_result = (result.existence, result.result)
185
186    def read_block_result_link(self, block_id):
187        # result is NOT protected from changing!
188        original_result_data = self._blocks_library[block_id][3]
189        result = ResultExistence(original_result_data[0], original_result_data[1])
190        # result = self._blocks_library[block_id][3]
191        return result
192
193    def read_block_result_copy(self, block_id):
194        original_result_data = self._blocks_library[block_id][3]
195        result = ResultExistence(original_result_data[0], copy.copy(original_result_data[1]))
196        return result
197
198    def read_block_result_deepcopy(self, block_id):
199        original_result_data = self._blocks_library[block_id][3]
200        result = ResultExistence(original_result_data[0], copy.deepcopy(original_result_data[1]))
201        return result
202
203    def _save_block_result(self, ignore_block_result_criteria=None):
204        # ignore_block_result_criteria = ignore_block_result_criteria or IgnoreBlockResultCriteriaType.do_not_ignore
205        if ((IgnoreBlockResultCriteriaType.ignore_if_failed == ignore_block_result_criteria) and
206                (not self._current_block_result[0])) \
207                or ((IgnoreBlockResultCriteriaType.ignore_if_successful == ignore_block_result_criteria) and
208                        self._current_block_result[0]):
209            return
210
211        self._bool_result()
212        import_depth = 0
213        full_block_info = (self._internal_blocks_index(), self._current_block_id, self._current_block_info,
214                           self._current_block_result, import_depth)
215        self._full_history.append(full_block_info)
216        self._blocks_library[self._current_block_id] = full_block_info
217        self._all_made_blocks.add(self._current_block_id)
218        if self._current_block_result[0]:
219            self._good_blocks.add(self._current_block_id)
220        else:
221            self._bad_blocks.add(self._current_block_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_blocks):
231                    result = False
232            elif CriteriaType.optional == current_criteria:
233                if len(self._bad_blocks - 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_blocks):
239                    result = False
240            elif CriteriaType.not_successful == current_criteria:
241                if len(current_criteria.result & self._good_blocks) != 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 _block_list_to_str(block_list):
251        blocks_str = ',\n'.join('(index({}), depth({}), ID({}), INFO({}), RESULT({}))'.format(str(block[0]),
252                                                                                              str(block[4]),
253                                                                                              str(block[1]),
254                                                                                              str(block[2]),
255                                                          '({}, {})'.format(str(block[3][0]), str(block[3][1])))
256                                for block in block_list)
257        return blocks_str
258
259    def _block_str_to_context_holder_str(self, blocks_str):
260        full_string = '{{{{CONTEXT_HOLDER_ID({}): CONTEXT_HOLDER_INFO({})}}:[\n{}\n]}}'.format(
261            self._context_holder_id, self._context_holder_info, blocks_str)
262        return full_string
263
264    def get_bad_blocks(self):
265        result = list()
266        for block in self._full_history:
267            if not block[3][0]:
268                result.append(block)
269        return result
270
271    def get_bad_blocks_str(self):
272        bad_blocks = self.get_bad_blocks()
273        full_history_str = self._block_list_to_str(bad_blocks)
274        full_string = self._block_str_to_context_holder_str(full_history_str)
275        return full_string
276
277    def raise_bad_blocks(self):
278        raise IsOK_HistoryExport(self.get_bad_blocks())
279
280    def raise_full_history(self):
281        raise IsOK_HistoryExport(self._full_history)
282
283    def process_history_import(self, his_ex):
284        history = his_ex.history
285        for block in history:
286            full_block_info = (self._internal_blocks_index.get_new_ID(), block[1], block[2],
287                               block[3], block[4] + 1)
288            self._full_history.append(full_block_info)
289
290    def close(self):
291        self._closed = True
292
293    def _reopen(self):
294        self._closed = False
295
296    def __str__(self):
297        full_history_str = self._block_list_to_str(self._full_history)
298        full_string = self._block_str_to_context_holder_str(full_history_str)
299        return full_string
300
301    def __call__(self, *args, **kwargs):
302        return is_ok(self, *args, **kwargs)
303
304    def is_ok(self, *args, **kwargs):
305        return self.__call__(*args, **kwargs)
IsOK_ContextHolder( context_holder_id=None, context_holder_info=None, global_block_results_criteria=None, raise_exceptions=False, save_debug_trace=False, closeable=True)
110    def __init__(self, context_holder_id=None, context_holder_info=None, global_block_results_criteria=None,
111                 raise_exceptions=False, save_debug_trace=False, closeable=True):
112        """
113
114        :param context_holder_id:
115        :param context_holder_info:
116        :param global_block_results_criteria: will be set to ResultType(CriteriaType.optional, set()) if None;
117            in this case all blocks are required.
118        :param raise_exceptions:
119        :param save_debug_trace:
120        :param closeable:
121        :return:
122        """
123        # Use only ResultType(CriteriaType.optional, ...) or ResultType(CriteriaType.needed, set()).
124        # Other will be ignored here.
125        # You may use global_block_results_criteria=ResultType(CriteriaType.optional, set()) to create criteria
126        # "no fails in any block"
127        self._context_holder_id = context_holder_id
128        self._context_holder_info = context_holder_info
129        self._internal_blocks_index = IDGenerator()
130        self._reserve_block_id_generator = IDGenerator(GeneratorType.guid_string)
131        self._criteria_list = list()
132        global_block_results_criteria = global_block_results_criteria or ResultType(CriteriaType.optional, set())
133        if global_block_results_criteria is not None:
134            self._criteria_list.append(global_block_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._blocks_library = dict()
140        self._all_made_blocks = set()
141        self._good_blocks = set()
142        self._bad_blocks = set()
143
144        self._current_block_id = None
145        self._current_block_info = None
146        self._current_block_result = None
147        self._closed = False
148
149        self._bool_result = ResultCache()

:param context_holder_id: :param context_holder_info: :param global_block_results_criteria: will be set to ResultType(CriteriaType.optional, set()) if None; in this case all blocks are required. :param raise_exceptions: :param save_debug_trace: :param closeable: :return:

def read_criteria(self):
163    def read_criteria(self):
164        criteria = None
165        if self._criteria_list:
166            criteria = self._criteria_list[-1]
167        return criteria
def push_result(self, bool_result, info_or_data=None):
179    def push_result(self, bool_result, info_or_data=None):
180        self._current_block_result = (bool_result, info_or_data)
def push_result_c(self, result):
182    def push_result_c(self, result):
183        # "class" version: to use when result = ResultExistence()
184        self._current_block_result = (result.existence, result.result)
def read_block_result_copy(self, block_id):
193    def read_block_result_copy(self, block_id):
194        original_result_data = self._blocks_library[block_id][3]
195        result = ResultExistence(original_result_data[0], copy.copy(original_result_data[1]))
196        return result
def read_block_result_deepcopy(self, block_id):
198    def read_block_result_deepcopy(self, block_id):
199        original_result_data = self._blocks_library[block_id][3]
200        result = ResultExistence(original_result_data[0], copy.deepcopy(original_result_data[1]))
201        return result
def get_bad_blocks(self):
264    def get_bad_blocks(self):
265        result = list()
266        for block in self._full_history:
267            if not block[3][0]:
268                result.append(block)
269        return result
def get_bad_blocks_str(self):
271    def get_bad_blocks_str(self):
272        bad_blocks = self.get_bad_blocks()
273        full_history_str = self._block_list_to_str(bad_blocks)
274        full_string = self._block_str_to_context_holder_str(full_history_str)
275        return full_string
def raise_bad_blocks(self):
277    def raise_bad_blocks(self):
278        raise IsOK_HistoryExport(self.get_bad_blocks())
def raise_full_history(self):
280    def raise_full_history(self):
281        raise IsOK_HistoryExport(self._full_history)
def process_history_import(self, his_ex):
283    def process_history_import(self, his_ex):
284        history = his_ex.history
285        for block in history:
286            full_block_info = (self._internal_blocks_index.get_new_ID(), block[1], block[2],
287                               block[3], block[4] + 1)
288            self._full_history.append(full_block_info)
def close(self):
290    def close(self):
291        self._closed = True
def is_ok(self, *args, **kwargs):
304    def is_ok(self, *args, **kwargs):
305        return self.__call__(*args, **kwargs)
@contextmanager
def is_ok( context_holder, block_id, block_info=None, block_results_criteria=None, ignore_block_result_criteria=None):
308@contextmanager
309def is_ok(context_holder, block_id, block_info=None, block_results_criteria=None, ignore_block_result_criteria=None):
310    if block_id is None:
311        new_id = context_holder._reserve_block_id_generator()
312        block_id = (new_id, new_id)
313
314    if context_holder._closeable and context_holder._closed:
315        raise IsOK_Closed(context_holder, block_id, block_info)
316
317    context_holder._push_block_info(block_id, block_info)
318    if block_results_criteria is not None:
319        context_holder._push_criteria(block_results_criteria)
320    need_to_save_block_result = True
321    try:
322        yield context_holder
323    except IsOK_BlockFailed as exc:
324        result_info = None
325        if exc.args:
326            result_info = exc.args[0]
327        context_holder.push_result(False, IsOK_IntenalResult(
328                IsOK_IntenalResultType.built_in_exception__is_ok_block_failed,
329                'ISOK INTERNAL RESULT. BUILT-IN EXCEPTION: IsOK_BlockFailed ({})'.format(result_info), result_info))
330    except IsOK_HistoryExport as export:
331        context_holder.process_history_import(export)
332        if export.process_error_result:
333            context_holder.push_result(False, IsOK_IntenalResult(
334                    IsOK_IntenalResultType.built_in_exception__bad_history_import,
335                    'ISOK INTERNAL RESULT. BUILT-IN EXCEPTION: BAD HISTORY IMPORT EXCEPTION', None))
336    except:
337        exc = sys.exc_info()
338        exc_type, exc_obj, exc_tb = exc
339        tb_full_file_name = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
340        tb_line_number = exc_tb.tb_lineno
341        tb_function_name = str()
342        tb_text = str()
343
344        tb_list = traceback.extract_tb(exc_tb, 2)
345        if len(tb_list) >= 2:
346            actual_tb = tb_list[1]
347            tb_full_file_name, tb_line_number, tb_function_name, tb_text = actual_tb
348
349        exception = exc
350        error_str = '{} {}'.format(str(exception[0]), str(exception[1].args[0]))
351        # print('+++', error_str)
352        formatted_traceback = traceback.format_exception(exception[0], exception[1], exception[2])
353        exception = exception[:2] + (formatted_traceback,)
354        trace_str = ''.join(exception[2])
355        if context_holder._save_debug_trace:
356            result_string = 'ISOK INTERNAL RESULT. CODE EXCEPTION "{}" AT "{}":{} in {} WITH TRACE: \n' \
357                            '{}\n' \
358                            '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~' \
359                            ''.format(error_str, tb_full_file_name, tb_line_number, tb_function_name, trace_str)
360        else:
361            result_string = 'ISOK INTERNAL RESULT. CODE EXCEPTION "{}" AT "{}":{} in {}'.format(
362                    error_str, tb_full_file_name, tb_line_number, tb_function_name)
363        context_holder.push_result(False, IsOK_IntenalResult(
364                IsOK_IntenalResultType.external_exception, result_string, exc))
365        # print(result_string)
366        # _is_ok_reader_runner__context_holder.push_result(False, sys.exc_info()[1])
367        if context_holder._raise_exceptions:
368            need_to_save_block_result = False
369            context_holder._save_block_result()
370            context_holder.raise_bad_blocks()
371            # raise
372    else:
373        if context_holder._current_block_result is None:
374            # _is_ok_reader_runner__context_holder.push_result(True)
375            context_holder.push_result(False, IsOK_IntenalResult(
376                    IsOK_IntenalResultType.block_did_not_returned_an_answer,
377                    'ISOK INTERNAL RESULT. BLOCK DID NOT RETURN RESULT', None))
378    finally:
379        if need_to_save_block_result:
380            context_holder._save_block_result(ignore_block_result_criteria)
381        if block_results_criteria is not None:
382            context_holder._pop_criteria()
383        context_holder._pop_block_info()
def is_ok__function(target_function):
386def is_ok__function(target_function):
387    """
388    Parameters: is_ok__context_holder= (required)
389        , is_ok__block_id= (required)
390        , is_ok__block_info= (optional)
391        , is_ok__block_results_criteria= (optional)
392        , is_ok__ignore_block_result_criteria= (optional).
393    Parameters passed to the target_function: is_ok__context_holder (after local block configuration).
394    :param target_function: function
395    :return:
396    """
397    def new_target_function(*args, **kwargs):
398        context_holder = None
399        if 'is_ok__context_holder' in kwargs:
400            context_holder = kwargs['is_ok__context_holder']
401            del kwargs['is_ok__context_holder']
402        else:
403            raise IsOKForFunction_ParameterNeeded('is_ok__context_holder')
404
405        block_id = None
406        if 'is_ok__block_id' in kwargs:
407            block_id = kwargs['is_ok__block_id']
408            del kwargs['is_ok__block_id']
409        else:
410            raise IsOKForFunction_ParameterNeeded('is_ok__block_id')
411
412        block_info = None
413        if 'is_ok__block_info' in kwargs:
414            block_info = kwargs['is_ok__block_info']
415            del kwargs['is_ok__block_info']
416
417        block_results_criteria = None
418        if 'is_ok__block_results_criteria' in kwargs:
419            block_results_criteria = kwargs['is_ok__block_results_criteria']
420            del kwargs['is_ok__block_results_criteria']
421
422        ignore_block_result_criteria = None
423        if 'is_ok__ignore_block_result_criteria' in kwargs:
424            ignore_block_result_criteria = kwargs['is_ok__ignore_block_result_criteria']
425            del kwargs['is_ok__ignore_block_result_criteria']
426
427        target_function_result = None
428        with is_ok(context_holder, block_id, block_info, block_results_criteria, ignore_block_result_criteria) as \
429                context:
430            kwargs['is_ok__context_holder'] = context
431            target_function_result = target_function(*args, **kwargs)
432
433        return target_function_result
434
435    return new_target_function

Parameters: is_ok__context_holder= (required) , is_ok__block_id= (required) , is_ok__block_info= (optional) , is_ok__block_results_criteria= (optional) , is_ok__ignore_block_result_criteria= (optional). Parameters passed to the target_function: is_ok__context_holder (after local block configuration). :param target_function: function :return:

class IsOkRunner:
469class IsOkRunner:
470    def __init__(self, current_globals, context_holder):
471        self.current_globals = current_globals
472        self.context_holder = context_holder
473
474    def __call__(self, block_id=None, block_info=None, block_results_criteria=None,
475                 ignore_block_result_criteria=None):
476        result = _IsOkRunner(self.current_globals, self.context_holder, block_id, block_info, block_results_criteria,
477                             ignore_block_result_criteria)
478        return result
IsOkRunner(current_globals, context_holder)
470    def __init__(self, current_globals, context_holder):
471        self.current_globals = current_globals
472        self.context_holder = context_holder
current_globals
context_holder
class IsOkCallRunner:
502class IsOkCallRunner:
503    def __init__(self, context_holder):
504        self.context_holder = context_holder
505
506    def __call__(self, block_id=None, block_info=None, block_results_criteria=None,
507                 ignore_block_result_criteria=None):
508        result = _IsOkCallRunner(self.context_holder, block_id, block_info, block_results_criteria,
509                                 ignore_block_result_criteria)
510        return result
IsOkCallRunner(context_holder)
503    def __init__(self, context_holder):
504        self.context_holder = context_holder
context_holder
def is_ok__function__simple(target_function):
513def is_ok__function__simple(target_function):
514    """
515    Parameters: is_ok__context_holder= (required)
516        , is_ok__block_id= (optional) (default value == str(target_function))
517        , is_ok__block_results_criteria= (optional)
518        , is_ok__ignore_block_result_criteria= (optional).
519    Parameters passed to the target_function: .
520    :param target_function: function
521    :return:
522    """
523    def new_target_function(*args, **kwargs):
524        context_holder = None
525        if 'is_ok__context_holder' in kwargs:
526            context_holder = kwargs['is_ok__context_holder']
527            del kwargs['is_ok__context_holder']
528        else:
529            raise IsOKForFunction_ParameterNeeded('is_ok__context_holder')
530
531        # block_id = '__UNNAMED_FUNCTION_SIMPLE_BLOCK__'
532        block_id = str(target_function)
533        if 'is_ok__block_id' in kwargs:
534            block_id = kwargs['is_ok__block_id']
535            del kwargs['is_ok__block_id']
536
537        block_results_criteria = None
538        if 'is_ok__block_results_criteria' in kwargs:
539            block_results_criteria = kwargs['is_ok__block_results_criteria']
540            del kwargs['is_ok__block_results_criteria']
541
542        ignore_block_result_criteria = None
543        if 'is_ok__ignore_block_result_criteria' in kwargs:
544            ignore_block_result_criteria = kwargs['is_ok__ignore_block_result_criteria']
545            del kwargs['is_ok__ignore_block_result_criteria']
546
547        target_function_result = None
548        with is_ok(context_holder, block_id, None, block_results_criteria, ignore_block_result_criteria) as context:
549            if context:
550                target_function_result = target_function(*args, **kwargs)
551                context.push_result(True, target_function_result)
552
553        return target_function_result
554
555    return new_target_function

Parameters: is_ok__context_holder= (required) , is_ok__block_id= (optional) (default value == str(target_function)) , is_ok__block_results_criteria= (optional) , is_ok__ignore_block_result_criteria= (optional). Parameters passed to the target_function: . :param target_function: function :return:

class IsOkUniRunner:
592class IsOkUniRunner:
593    def __init__(self, current_globals, context_holder, simple_mode=False, function_result_criteria=None):
594        self.current_globals = current_globals
595        self.context_holder = context_holder
596        self.simple_mode = simple_mode
597        self.default_function_result_criteria = function_result_criteria or (lambda result: True)
598        self.function_result_criteria = self.default_function_result_criteria
599
600        self.runner_class = _IsOkRunner
601        if self.simple_mode:
602            self.runner_class = _IsOkRunnerSimple
603
604    def set_function_result_criteria(self, result_criteria_computer):
605        self.function_result_criteria = result_criteria_computer
606
607    def reset_function_result_criteria(self):
608        self.function_result_criteria = self.default_function_result_criteria
609
610    def __call__(self, block_id=None, block_info=None, block_results_criteria=None,
611                 ignore_block_result_criteria=None):
612        result = self.runner_class(self.current_globals, self.context_holder, block_id, block_info,
613                                   block_results_criteria, ignore_block_result_criteria, self.function_result_criteria)
614        return result
IsOkUniRunner( current_globals, context_holder, simple_mode=False, function_result_criteria=None)
593    def __init__(self, current_globals, context_holder, simple_mode=False, function_result_criteria=None):
594        self.current_globals = current_globals
595        self.context_holder = context_holder
596        self.simple_mode = simple_mode
597        self.default_function_result_criteria = function_result_criteria or (lambda result: True)
598        self.function_result_criteria = self.default_function_result_criteria
599
600        self.runner_class = _IsOkRunner
601        if self.simple_mode:
602            self.runner_class = _IsOkRunnerSimple
current_globals
context_holder
simple_mode
default_function_result_criteria
function_result_criteria
runner_class
def set_function_result_criteria(self, result_criteria_computer):
604    def set_function_result_criteria(self, result_criteria_computer):
605        self.function_result_criteria = result_criteria_computer
def reset_function_result_criteria(self):
607    def reset_function_result_criteria(self):
608        self.function_result_criteria = self.default_function_result_criteria
class IsOkUniCallRunner:
641class IsOkUniCallRunner:
642    def __init__(self, context_holder, simple_mode=False, function_result_criteria=None):
643        self.context_holder = context_holder
644        self.simple_mode = simple_mode
645        self.default_function_result_criteria = function_result_criteria or (lambda result: True)
646        self.function_result_criteria = self.default_function_result_criteria
647
648        self.runner_class = _IsOkCallRunner
649        if self.simple_mode:
650            self.runner_class = _IsOkCallRunnerSimple
651
652    def set_function_result_criteria(self, result_criteria_computer):
653        self.function_result_criteria = result_criteria_computer
654
655    def reset_function_result_criteria(self):
656        self.function_result_criteria = self.default_function_result_criteria
657
658    def __call__(self, block_id=None, block_info=None, block_results_criteria=None,
659                 ignore_block_result_criteria=None):
660        result = self.runner_class(self.context_holder, block_id, block_info,
661                                   block_results_criteria, ignore_block_result_criteria, self.function_result_criteria)
662        return result
IsOkUniCallRunner(context_holder, simple_mode=False, function_result_criteria=None)
642    def __init__(self, context_holder, simple_mode=False, function_result_criteria=None):
643        self.context_holder = context_holder
644        self.simple_mode = simple_mode
645        self.default_function_result_criteria = function_result_criteria or (lambda result: True)
646        self.function_result_criteria = self.default_function_result_criteria
647
648        self.runner_class = _IsOkCallRunner
649        if self.simple_mode:
650            self.runner_class = _IsOkCallRunnerSimple
context_holder
simple_mode
default_function_result_criteria
function_result_criteria
runner_class
def set_function_result_criteria(self, result_criteria_computer):
652    def set_function_result_criteria(self, result_criteria_computer):
653        self.function_result_criteria = result_criteria_computer
def reset_function_result_criteria(self):
655    def reset_function_result_criteria(self):
656        self.function_result_criteria = self.default_function_result_criteria
class IsOkValRunner:
692class IsOkValRunner:
693    def __init__(self, context_holder, function_result_criteria=None, reaction_to_the_result=None):
694        self.context_holder = context_holder
695        self.default_function_result_criteria = function_result_criteria or (lambda result: True)
696        self.function_result_criteria = self.default_function_result_criteria
697        self.reaction_to_the_result = reaction_to_the_result
698
699    def set_function_result_criteria(self, result_criteria_computer):
700        self.function_result_criteria = result_criteria_computer
701
702    def reset_function_result_criteria(self):
703        self.function_result_criteria = self.default_function_result_criteria
704
705    def __call__(self, block_id=None, block_info=None, block_results_criteria=None,
706                 ignore_block_result_criteria=None):
707        result = _IsOkValRunner(self.context_holder, block_id, block_info,
708                                block_results_criteria, ignore_block_result_criteria,
709                                self.function_result_criteria, self.reaction_to_the_result)
710        return result
IsOkValRunner( context_holder, function_result_criteria=None, reaction_to_the_result=None)
693    def __init__(self, context_holder, function_result_criteria=None, reaction_to_the_result=None):
694        self.context_holder = context_holder
695        self.default_function_result_criteria = function_result_criteria or (lambda result: True)
696        self.function_result_criteria = self.default_function_result_criteria
697        self.reaction_to_the_result = reaction_to_the_result
context_holder
default_function_result_criteria
function_result_criteria
reaction_to_the_result
def set_function_result_criteria(self, result_criteria_computer):
699    def set_function_result_criteria(self, result_criteria_computer):
700        self.function_result_criteria = result_criteria_computer
def reset_function_result_criteria(self):
702    def reset_function_result_criteria(self):
703        self.function_result_criteria = self.default_function_result_criteria
@contextmanager
def is_ok_reader(context_holder, block_results_criteria=None, close=False):
713@contextmanager
714def is_ok_reader(context_holder, block_results_criteria=None, close=False):
715    if block_results_criteria is not None:
716        context_holder._push_criteria(block_results_criteria)
717    try:
718        yield context_holder
719    except:
720        raise
721    finally:
722        if block_results_criteria is not None:
723            context_holder._pop_criteria()
724        if close:
725            context_holder.close()
def is_ok_reader__function(target_function):
728def is_ok_reader__function(target_function):
729    """
730    Parameters: is_ok__context_holder= (required), is_ok__block_results_criteria= (optional), is_ok__close= (optional).
731    Parameters passed to the target_function: is_ok__context_holder (after local block configuration).
732    :param target_function: function
733    :return:
734    """
735    def new_target_function(*args, **kwargs):
736        context_holder = None
737        if 'is_ok__context_holder' in kwargs:
738            context_holder = kwargs['is_ok__context_holder']
739            del kwargs['is_ok__context_holder']
740        else:
741            raise IsOKForFunction_ParameterNeeded('is_ok__context_holder')
742
743        block_results_criteria = None
744        if 'is_ok__block_results_criteria' in kwargs:
745            block_results_criteria = kwargs['is_ok__block_results_criteria']
746            del kwargs['is_ok__block_results_criteria']
747
748        close = None
749        if 'is_ok__close' in kwargs:
750            close = kwargs['is_ok__close']
751            del kwargs['is_ok__close']
752
753        target_function_result = None
754        with is_ok_reader(context_holder, block_results_criteria, close) as context:
755            kwargs['is_ok__context_holder'] = context
756            target_function_result = target_function(*args, **kwargs)
757
758        return target_function_result
759
760    return new_target_function

Parameters: is_ok__context_holder= (required), is_ok__block_results_criteria= (optional), is_ok__close= (optional). Parameters passed to the target_function: is_ok__context_holder (after local block configuration). :param target_function: function :return:

class IsOkReaderRunner:
790class IsOkReaderRunner:
791    def __init__(self, current_globals, context_holder):
792        self.current_globals = current_globals
793        self.context_holder = context_holder
794
795    def __call__(self, block_results_criteria=None, close=False):
796        result = _IsOkReaderRunner(self.current_globals, self.context_holder, block_results_criteria, close)
797        return result
IsOkReaderRunner(current_globals, context_holder)
791    def __init__(self, current_globals, context_holder):
792        self.current_globals = current_globals
793        self.context_holder = context_holder
current_globals
context_holder
class IsOkReaderCallRunner:
817class IsOkReaderCallRunner:
818    def __init__(self, context_holder):
819        self.context_holder = context_holder
820
821    def __call__(self, block_results_criteria=None, close=False):
822        result = _IsOkReaderCallRunner(self.context_holder, block_results_criteria, close)
823        return result
IsOkReaderCallRunner(context_holder)
818    def __init__(self, context_holder):
819        self.context_holder = context_holder
context_holder