from typing import Optional
from typing import Union


def parse_positive_integer(s: 'Optional[Union[str, int]]') -> 'Optional[int]':
    """Parse a positive integer from a string representation.

    Args:
        s: string representation of a positive integer, or just an integer

    Returns:
        the parsed integer result, return :data:`None` if input is :data:`None` or empty string

    Raises:
        TypeError: if ``s`` is not :obj:`str` or :obj:`int`
        ValueError: if ``s`` is an invalid positive integer value

    """
    if s is None or s == '':  # pylint: disable=compare-to-empty-string
        return None
    if not isinstance(s, (str, int)):
        raise TypeError('expect str or int, got {!r}'.format(s))
    try:
        value = int(s)
    except ValueError:
        raise ValueError('expect an integer value, got {!r}'.format(s)) from None
    if value <= 0:
        raise ValueError('expect integer value to be positive, got {!r}'.format(value))
    return value