def field_to_swagger_object(self, field, swagger_object_type, use_references, **kwargs): if not isinstance(field, serializers.SerializerMethodField): return NotHandled method = getattr(field.parent, field.method_name) if method is None: return NotHandled # attribute added by the swagger_serializer_method decorator serializer = getattr(method, "_swagger_serializer", None) if serializer: # in order of preference for description, use: # 1) field.help_text from SerializerMethodField(help_text) # 2) serializer.help_text from swagger_serializer_method(serializer) # 3) method's docstring description = field.help_text if description is None: description = getattr(serializer, 'help_text', None) if description is None: description = method.__doc__ label = field.label if label is None: label = getattr(serializer, 'label', None) if inspect.isclass(serializer): serializer_kwargs = { "help_text": description, "label": label, "read_only": True, } serializer = method._swagger_serializer(**serializer_kwargs) else: serializer.help_text = description serializer.label = label serializer.read_only = True return self.probe_field_inspectors(serializer, swagger_object_type, use_references, read_only=True) elif typing and inspect_signature: # look for Python 3.5+ style type hinting of the return value hint_class = inspect_signature(method).return_annotation if inspect.isclass(hint_class) and not issubclass( hint_class, inspect._empty): type_info = get_basic_type_info_from_hint(hint_class) if type_info is not None: SwaggerType, ChildSwaggerType = self._get_partial_types( field, swagger_object_type, use_references, **kwargs) return SwaggerType(**type_info) return NotHandled
def code_obj_to_signature(code_obj: CodeType) -> str: """Get a function signature from a code object. See: https://stackoverflow.com/a/56761306/5094008 """ try: func = FunctionType(code_obj, {}) arg_sequence = inspect_signature(func) return f'def {code_obj.co_name}{arg_sequence}:' except TypeError: # build our own signature return f"""\
def __get_final_inner_function(self): """ Returns a string of an generated inner function with the code body from: func Tries to generate a new function with the 'code-body' from the `self.func` as well as the `self.args_list` and `self.kwargs_dict` :return: (str) generated inner function) :raise Err: example if an indentation is encountered which is not a multiple of the first found indentation """ has_block_speedit = False _start_block_stripped_line = '' start_tag_block_speedit = 0 end_tag_block_speedit = 0 func_line, l_num = inspect_getsourcelines(self.func) sig = inspect_signature(self.func) indent_ = None func_def_indent = len(func_line[0]) - len(func_line[0].lstrip()) func_body = func_line[1:] search_docstring = False # PREPARE: remove docstring and get final indentation first_none_docstring_idx = 0 for idx, line_orig in enumerate(func_body): rstripped_line = line_orig.rstrip() if rstripped_line: stripped_codeline = rstripped_line.lstrip() if stripped_codeline[0] == '#': # remove comment lines if not ('::SPEEDIT::' in stripped_codeline or '**SPEEDIT**' in stripped_codeline): continue if search_docstring: if stripped_codeline[0:3] == '"""' or stripped_codeline[0:3] == "'''": search_docstring = False continue else: codebody_indent = len(rstripped_line) - len(stripped_codeline) indent_ = codebody_indent - func_def_indent # Check if we have a docstring if stripped_codeline[0:3] == '"""' or stripped_codeline[0:3] == "'''": search_docstring = True continue first_none_docstring_idx = idx break # do the func code body adjusted_func_code_line = [] for line_orig in func_body[first_none_docstring_idx:]: # remove empty if line_orig: # get indentation check it is a multiple of indent_ rstrip_line = line_orig.rstrip() if rstrip_line: stripped_line = rstrip_line.lstrip() if stripped_line[0] == '#': # remove comment lines: keep any with ::SPEEDIT:: if '::SPEEDIT::' in stripped_line or '**SPEEDIT**' in stripped_line: has_block_speedit = True else: continue line_indentation = len(rstrip_line) - len(stripped_line) if line_indentation % indent_ != 0: raise Err('_TimeIT.get_final_inner_function', [ '<{}>: ERROR: indentation must be a multiple of the second function line: <{}>'.format( self.orig_func_name, indent_ ), ' seems we encountered a wrong indented line: line_indentation: <{}>'.format(line_indentation), ' {}'.format(line_orig) ]) line_indentation_level = int((line_indentation - func_def_indent) / indent_) + 1 # need one extra level if has_block_speedit: if '::SPEEDIT::' in stripped_line: if start_tag_block_speedit != end_tag_block_speedit: # expected END Tag raise Err('_TimeIT.get_final_inner_function', [ '<{}>: FUNCTION INNER TAG ERROR: has_block_speedit: <{}>'.format( self.orig_func_name, has_block_speedit ), ' Expected an END-TAG <**SPEEDIT**>: ' ' {}'.format(line_orig) ]) adjusted_func_code_line.append( (' ' * line_indentation_level) + '_speedit_prefix__stmt_inner_start = _speedit_prefix__perf_counter() # ::SPEEDIT::START internally added' ) start_tag_block_speedit += 1 _start_block_stripped_line = stripped_line elif '**SPEEDIT**' in stripped_line: if end_tag_block_speedit != start_tag_block_speedit - 1: # expected START TAG raise Err('_TimeIT.get_final_inner_function', [ '<{}>: FUNCTION INNER TAG ERROR: has_block_speedit: <{}>'.format( self.orig_func_name, has_block_speedit), ' Expected an START-TAG <::SPEEDIT::>:', ' {}'.format(line_orig) ]) # Do this inner result adjusted_func_code_line.append(( ' ' * line_indentation_level) + '_speedit_prefix__result_time += _speedit_prefix__perf_counter() - _speedit_prefix__stmt_inner_start # **SPEEDIT**END internally added') if self.check_too_fast: adjusted_func_code_line.append( (' ' * line_indentation_level) + 'if _speedit_prefix__result_time < _speedit_prefix__check_reference_time: raise Exception("in function: <{}>'.format( self.orig_func_name) + ' code block: too fast to measure:\\n code part: _speedit_prefix__result_time: <{:.11f}> 2 times _smallest_perf_counter_time: <{:.11f}>\\n ' + ' _start_block_stripped_line: <{}>'.format( _start_block_stripped_line) + '".format(_speedit_prefix__result_time, _speedit_prefix__check_reference_time)) # SPEEDIT: internally added') end_tag_block_speedit += 1 else: adjusted_func_code_line.append((' ' * line_indentation_level) + stripped_line) else: adjusted_func_code_line.append((' ' * line_indentation_level) + stripped_line) # CHECK: LAST END TAG # e.g. if a function body ends with an END-TAG this is not returned by: inspect.getsourcelines(self.func) if has_block_speedit: if start_tag_block_speedit != end_tag_block_speedit: # Do the last inner result: ADDING an END-TAG adjusted_func_code_line.append( ' _speedit_prefix__result_time += _speedit_prefix__perf_counter() - _speedit_prefix__stmt_inner_start # **SPEEDIT**END internally added') if self.check_too_fast: adjusted_func_code_line.append( ' if _speedit_prefix__result_time < _speedit_prefix__check_reference_time: raise Exception("in function: <{}>'.format( self.orig_func_name) + ' code block: too fast to measure:\\n code part: _speedit_prefix__result_time: <{:.11f}> 2 times _smallest_perf_counter_time: <{:.11f}>\\n ' + ' _start_block_stripped_line: <{}>'.format( _start_block_stripped_line) + '".format(_speedit_prefix__result_time, _speedit_prefix__check_reference_time)) # SPEEDIT: internally added') # add the normal perf_counter time lines else: adjusted_func_code_line.insert( 0, ' _speedit_prefix__stmt_inner_start = _speedit_prefix__perf_counter() # ::SPEEDIT::START internally added' ) adjusted_func_code_line.append( ' _speedit_prefix__result_time += _speedit_prefix__perf_counter() - _speedit_prefix__stmt_inner_start # **SPEEDIT**END internally added') if self.check_too_fast: adjusted_func_code_line.append( ' if _speedit_prefix__result_time < _speedit_prefix__check_reference_time: raise Exception("in function: <{}>'.format( self.orig_func_name) + ' code block: too fast to measure:\\n code part: _speedit_prefix__result_time: <{:.11f}> 2 times _smallest_perf_counter_time: <{:.11f}>".format(_speedit_prefix__result_time, _speedit_prefix__check_reference_time)) # SPEEDIT: internally added') # Do the arguments final_param_line = [] for param, value in sig.parameters.items(): if value.kind == value.POSITIONAL_OR_KEYWORD: # check if we have a keyword if param in self.kwargs_dict: value_to_set = self.kwargs_dict.pop(param) else: # use any positional if not self.args_list: raise Err('_TimeIT.__get_final_inner_function', [ 'orig_func_name: <{}>'.format(self.orig_func_name), ' POSITIONAL_OR_KEYWORD ERROR: seems no such keyword nor enough positional arguments are supplied', ' param: <{}>'.format(param), ' list_of_positional_arguments: <{}>'.format(self.args_list), ' dictionary_of_keyword_arguments: <{}>'.format(self.kwargs_dict), ]) value_to_set = self.args_list.pop(0) if isinstance(value_to_set, str): parameter_line = '{} = "{}"'.format(param, value_to_set) else: parameter_line = '{} = {}'.format(param, value_to_set) final_param_line.append((' ' * 2) + parameter_line) elif value.kind == value.POSITIONAL_ONLY: value_to_set = self.args_list.pop(0) if isinstance(value_to_set, str): parameter_line = '{} = "{}"'.format(param, value_to_set) else: parameter_line = '{} = {}'.format(param, value_to_set) final_param_line.append((' ' * 2) + parameter_line) # TODO: From docs: 3.4 Python has no explicit syntax for defining positional-only parameters, but many built-in and extension module functions (especially those that accept only one or two parameters) accept them. raise Err('_TimeIT.get_final_inner_function()', [ 'orig_func_name: <{}>'.format(self.orig_func_name), ' POSITIONAL_ONLY !! not sure what to do .. check in future if needed:', ' param: <{}> value.kind: <{}>'.format(param, value.kind) ]) elif value.kind == value.VAR_POSITIONAL: # do the remaining POSITIONAL arguments parameter_line = '{} = {}'.format(param, self.args_list) final_param_line.append((' ' * 2) + parameter_line) elif value.kind == value.KEYWORD_ONLY: if param in self.kwargs_dict: value_to_set = self.kwargs_dict.pop(param) else: # use the default value_to_set = value.default if isinstance(value_to_set, str): parameter_line = '{} = "{}"'.format(param, value_to_set) else: parameter_line = '{} = {}'.format(param, value_to_set) final_param_line.append((' ' * 2) + parameter_line) elif value.kind == value.VAR_KEYWORD: # do the remaining KEYWORD arguments parameter_line = '{} = {}'.format(param, self.kwargs_dict) final_param_line.append((' ' * 2) + parameter_line) else: continue final_inner_function_lines = [ 'def inner(): # orig function name: {}'.format(self.orig_func_name), ' from time import perf_counter as _speedit_prefix__perf_counter', '', ' _speedit_prefix__run_sec = {}'.format(self.run_sec), '', ' # The smallest difference of calling _speedit_prefix__perf_counter() ', ' # immediately after each other a couple of times', ' _speedit_prefix__check_reference_time = {}'.format(self.perf_counter_reference_time), ' _speedit_prefix__loops = 0', ' _speedit_prefix__all_loops_time_sec = 0.0', ' _speedit_prefix__avg_loop_sec = 0.0', ' _speedit_prefix__best_loop_sec = 99999999999.0', ' _speedit_prefix__second_best_loop_sec = 99999999999.0', ' _speedit_prefix__worst_loop_sec = 0.0', ' _speedit_prefix__second_worst_loop_sec = 0.0', ' if _speedit_prefix__run_sec == -1:', ' # only run it once', ' _speedit_prefix__run_once = True', ' else:', ' _speedit_prefix__run_once = False', ' _speedit_prefix__main_start_time = _speedit_prefix__perf_counter()', ' while True:', ' _speedit_prefix__loops += 1', ' _speedit_prefix__result_time = 0', '', ' # ==================== START CODE BLOCK ==================== #', '', ] final_inner_function_lines.extend(final_param_line) final_inner_function_lines.extend(adjusted_func_code_line) inner_function_lines_rest = [ '', ' # ==================== END CODE BLOCK ==================== #', '', ' _speedit_prefix__all_loops_time_sec += _speedit_prefix__result_time', ' if _speedit_prefix__result_time <= _speedit_prefix__best_loop_sec:', ' _speedit_prefix__second_best_loop_sec = _speedit_prefix__best_loop_sec', ' _speedit_prefix__best_loop_sec = _speedit_prefix__result_time', ' if _speedit_prefix__result_time >= _speedit_prefix__worst_loop_sec:', ' _speedit_prefix__second_worst_loop_sec = _speedit_prefix__worst_loop_sec', ' _speedit_prefix__worst_loop_sec = _speedit_prefix__result_time', ' if _speedit_prefix__run_once:', ' break', ' # check if we have to get out', ' if _speedit_prefix__perf_counter() - _speedit_prefix__main_start_time >= _speedit_prefix__run_sec:', ' break', ' _speedit_prefix__avg_loop_sec = _speedit_prefix__all_loops_time_sec / _speedit_prefix__loops', ' if _speedit_prefix__second_best_loop_sec == 99999999999.0:', ' _speedit_prefix__second_best_loop_sec = -1.0', ' if _speedit_prefix__second_worst_loop_sec == 0.0:', ' _speedit_prefix__second_worst_loop_sec = -1.0', ' return {', ' "loops": _speedit_prefix__loops,', ' "all_loops_time_sec": _speedit_prefix__all_loops_time_sec,', ' "avg_loop_sec": _speedit_prefix__avg_loop_sec,', ' "best_loop_sec": _speedit_prefix__best_loop_sec,', ' "second_best_loop_sec": _speedit_prefix__second_best_loop_sec,', ' "worst_loop_sec": _speedit_prefix__worst_loop_sec,', ' "second_worst_loop_sec": _speedit_prefix__second_worst_loop_sec', ' }', '' ] final_inner_function_lines.extend(inner_function_lines_rest) return '\n'.join(final_inner_function_lines)
def parameter_names(self): r""" Return the names of the parameters in this model. """ return tuple(inspect_signature(self.expectation).parameters.keys())[1:]