def repeated(pattern, sep, least=1, most=None):
    """
    Returns a pattern that matches a sequence of strings that match ``pattern`` separated by strings
    that match ``sep``.

    For example, for matching a sequence of ``'{key}={value}'`` pairs separated by ``'&'``, where
    key and value contains only lowercase letters::

        repeated('[a-z]+=[a-z]+', '&') == '[a-z]+=[a-z]+(?:&[a-z]+=[a-z]+)*'

    Args:
        pattern (str):
            a pattern
        sep (str):
            a pattern for the separator (usually just a character/string)
        least (int, positive):
            minimum number of strings matching ``pattern``; must be positive
        most (Optional[int]):
            maximum number of strings matching ``pattern``; must be greater or equal to ``least``

    Returns:
        a pattern

    """
    if least <= 0:
        raise ValueError('least should be positive; it is: %d' % least)
    if most is not None:
        if most < 2:
            raise ValueError('it does not make any sense to call this function with most<2:\n'
                             'for most=1, you could just write the <pattern> argument')
        if most < least:
            raise ValueError('most must be greater or equal to least')

    least_s = str(least - 1) if least > 1 else ''
    most_s = str(most - 1) if most else ''

    if most and least == most:
        if least == 2:
            return pattern + sep + pattern
        reps = '{%s}' % least_s
    else:
        reps = '{%s,%s}' % (least_s, most_s)

        if reps == '{,}':
            reps = '*'
        elif reps == '{1,}':
            reps = '+'
        elif reps == '{,1}':
            reps = '?'

    return ('{pattern}(?:{sep}{pattern}){reps}'
            .format(pattern=pattern, sep=sep, reps=reps))