code: def weak_composition_iter(n: int, num_parts: int) -> Iterator[Tuple[int, ...]]:
      
      if n < 0:
          raise ValueError("Total must not be negative")
      if num_parts < 0:
          raise ValueError("Number of num_parts must not be negative")
      if num_parts == 0:
          if n == 0:
              yield tuple()
          return
      m = n + num_parts - 1
      last = (m, )
      first = (-1, )
      for t in itertools.combinations(range(m), num_parts - 1):
          yield tuple(v - u - 1 for u, v in zip(first + t, t + last))
docs: Yield all weak compositions of integer *n* into *num_parts* parts.
  
      Each composition is yielded as a tuple. The generated partitions are order-dependant and not unique when
      ignoring the order of the components. The partitions are yielded in lexicographical order.
  
      Example:
  
          >>> compositions = list(weak_composition_iter(5, 2))
          >>> compositions
          [(0, 5), (1, 4), (2, 3), (3, 2), (4, 1), (5, 0)]
  
          We can easily verify that all compositions are indeed valid:
  
          >>> list(map(sum, compositions))
          [5, 5, 5, 5, 5, 5]
  
      The algorithm was adapted from an answer to this `Stackoverflow question`_.
  
      Args:
          n:
              The integer to partition.
          num_parts:
              The number of parts for the combination.
  
      Yields:
          All non-negative tuples that have the given sum and size.
  
      Raises:
          ValueError:
              If *n* or *num_parts* are negative.
  
      .. _Stackoverflow question: http://stackoverflow.com/questions/40538923/40540014#40540014