docs: def convert_collection_values_according_to_pep(coll_to_convert: Union[Dict, List, Set, Tuple],
                                                     desired_type: Type[T],
                                                     conversion_finder: 'ConversionFinder', logger: Logger, **kwargs) \
              -> T:
          """
          Helper method to convert the values of a collection into the required (pep-declared) value type in desired_type.
          If desired_type does not explicitly mention a type for its values, the collection will be returned as is, otherwise
          a  copy will be created and filled with conversions of the values, performed by the provided conversion_finder
  
          :param coll_to_convert:
          :param desired_type:
          :param conversion_finder:
          :param logger:
          :param kwargs:
          :return:
          """
          base_desired_type = get_base_generic_type(desired_type)
  
          if issubclass(base_desired_type, Mapping):  # or issubclass(base_desired_type, dict):
              # get the base collection type if provided (this raises an error if key type is not str)
              item_typ, _ = _extract_collection_base_type(desired_type, exception_if_none=False)
  
              if item_typ is None:
                  # nothing is required in terms of dict values: use the base method
                  return ConversionFinder.try_convert_value(conversion_finder, '', coll_to_convert, desired_type,
                                                            logger=logger, options=kwargs)
              else:
                  # TODO resuse appropriate container type (not necessary a dict) according to type of coll_to_convert
                  # there is a specific type required for the dict values.
                  res = dict()
                  # convert if required
                  for key, val in coll_to_convert.items():
                      res[key] = ConversionFinder.try_convert_value(conversion_finder, key, val, item_typ, logger,
                                                                    options=kwargs)
                  return res
  
          elif issubclass(base_desired_type, Sequence):  # or issubclass(base_desired_type, list):
              # get the base collection type if provided
              item_typ, _ = _extract_collection_base_type(desired_type, exception_if_none=False)
  
              if item_typ is None:
                  # nothing is required in terms of dict values: use the base method
                  return ConversionFinder.try_convert_value(conversion_finder, '', coll_to_convert, desired_type,
                                                            logger=logger, options=kwargs)
              else:
                  # TODO resuse appropriate container type (not necessary a list) according to type of coll_to_convert
                  # there is a specific type required for the list values.
                  res = list()
  
                  # special case where base_desired_type is a Tuple: in that case item_typ may be a tuple or else
                  if type(item_typ) != tuple:
                      # convert each item if required
                      for val in coll_to_convert:
                          res.append(ConversionFinder.try_convert_value(conversion_finder, '', val, item_typ, logger,
                                                                        options=kwargs))
                  else:
                      if len(item_typ) == 1:
                          item_typ_tuple = item_typ * len(coll_to_convert)
                      elif len(item_typ) == len(coll_to_convert):
                          item_typ_tuple = item_typ
                      else:
                          raise ValueError('Collection to convert is of length {} which is not compliant with desired '
                                           'type {}'.format(len(coll_to_convert), item_typ))
                      for val, item_t in zip(coll_to_convert, item_typ_tuple):
                          res.append(ConversionFinder.try_convert_value(conversion_finder, '', val, item_t, logger,
                                                                        options=kwargs))
                      res = tuple(res)
  
                  return res
  
          elif issubclass(base_desired_type, AbstractSet):  # or issubclass(base_desired_type, set):
              # get the base collection type if provided
              item_typ, _ = _extract_collection_base_type(desired_type, exception_if_none=False)
  
              if item_typ is None:
                  # nothing is required in terms of dict values: use the base method
                  return ConversionFinder.try_convert_value(conversion_finder, '', coll_to_convert, desired_type,
                                                            logger=logger, options=kwargs)
              else:
                  # TODO resuse appropriate container type (not necessary a set) according to type of coll_to_convert
                  # there is a specific type required for the list values.
                  res = set()
                  # convert if required
                  for val in coll_to_convert:
                      res.add(ConversionFinder.try_convert_value(conversion_finder, '', val, item_typ, logger,
                                                                 options=kwargs))
                  return res
  
          else:
              raise TypeError('Cannot convert collection values, expected type is not a supported collection '
                              '(dict, list, set, Mapping, Sequence, AbstractSet)! : ' + str(desired_type))