docs: def resolve_dynamic_values(env):
      """
      Resolve dynamic values inside need data.
  
      Rough workflow:
  
      #. Parse all needs and their data for a string like [[ my_func(a,b,c) ]]
      #. Extract function name and call parameters
      #. Execute registered function name with extracted call parameters
      #. Replace original string with return value
  
      :param env: Sphinx environment
      :return: return value of given function
      """
      # Only perform calculation if not already done yet
      if env.needs_workflow['dynamic_values_resolved']:
          return
  
      needs = env.needs_all_needs
      for key, need in needs.items():
          for need_option in need:
              if need_option in ['docname', 'lineno', 'target_node', 'content']:
                  # dynamic values in this data are not allowed.
                  continue
              if not isinstance(need[need_option], (list, set)):
                  func_call = True
                  while func_call:
                      try:
                          func_call, func_return = _detect_and_execute(need[need_option], need, env)
                      except FunctionParsingException:
                          raise SphinxError("Function definition of {option} in file {file}:{line} has "
                                            "unsupported parameters. "
                                            "supported are str, int/float, list".format(option=need_option,
                                                                                        file=need['docname'],
                                                                                        line=need['lineno']))
  
                      if func_call is None:
                          continue
                      # Replace original function string with return value of function call
                      if func_return is None:
                          need[need_option] = need[need_option].replace('[[{}]]'.format(func_call), '')
                      else:
                          need[need_option] = need[need_option].replace('[[{}]]'.format(func_call), str(func_return))
  
                      if need[need_option] == '':
                          need[need_option] = None
              else:
                  new_values = []
                  for element in need[need_option]:
                      try:
                          func_call, func_return = _detect_and_execute(element, need, env)
                      except FunctionParsingException:
                          raise SphinxError("Function definition of {option} in file {file}:{line} has "
                                            "unsupported parameters. "
                                            "supported are str, int/float, list".format(option=need_option,
                                                                                        file=need['docname'],
                                                                                        line=need['lineno']))
                      if func_call is None:
                          new_values.append(element)
                      else:
                          # Replace original function string with return value of function call
                          if isinstance(need[need_option], (str, int, float)):
                              new_values.append(element.replace('[[{}]]'.format(func_call), str(func_return)))
                          else:
                              if isinstance(need[need_option], (list, set)):
                                  new_values += func_return
  
                  need[need_option] = new_values
  
      # Finally set a flag so that this function gets not executed several times
      env.needs_workflow['dynamic_values_resolved'] = True