def _section_execution_order(self, section, iterargs
                             , reverse=False
                             , custom_order=None
                             , explicit_checks: Iterable = None
                             , exclude_checks: Iterable = None):
    """
      order must:
        a) contain all variable args (we're appending missing ones)
        b) not contian duplictates (we're removing repeated items)

      order may contain *iterargs otherwise it is appended
      to the end

      order may contain "*check" otherwise, it is like *check is appended
      to the end (Not done explicitly though).
    """
    stack = list(custom_order) if custom_order is not None else list(section.order)
    if '*iterargs' not in stack:
      stack.append('*iterargs')
    stack.reverse()

    full_order = []
    seen = set()
    while len(stack):
      item = stack.pop()
      if item in seen:
        continue
      seen.add(item)
      if item == '*iterargs':
        all_iterargs = list(iterargs.keys())
        # assuming there is a meaningful order
        all_iterargs.reverse()
        stack += all_iterargs
        continue
      full_order.append(item)

    # Filter down checks. Checks to exclude are filtered for last as the user
    # might e.g. want to include all tests with "kerning" in the ID, except for
    # "kerning_something". explicit_checks could then be ["kerning"] and
    # exclude_checks ["something"].
    checks = section.checks
    if explicit_checks:
      checks = [
          check for check in checks
          if any(include_string in check.id for include_string in explicit_checks)
      ]
    if exclude_checks:
      checks = [
          check for check in checks
          if not any(exclude_string in check.id for exclude_string in exclude_checks)
      ]

    scopes = self._analyze_checks(full_order, checks)
    key = lambda item: item[1] # check, signature, scope = item
    scopes.sort(key=key, reverse=reverse)

    for check, args in self._execute_scopes(iterargs, scopes):
      # this is the iterargs tuple that will be used as a key for caching
      # and so on. we could sort it, to ensure it yields in the same
      # cache locations always, but then again, it is already in a well
      # defined order, by clustering.
      yield check, tuple(args)
order must:
        a) contain all variable args (we're appending missing ones)
        b) not contian duplictates (we're removing repeated items)

      order may contain *iterargs otherwise it is appended
      to the end

      order may contain "*check" otherwise, it is like *check is appended
      to the end (Not done explicitly though).