def phmsdms(hmsdms):
units = None<EOL>sign = None<EOL>pattern1 = re.compile(r"<STR_LIT>")<EOL>pattern2 = re.compile(r"<STR_LIT>")<EOL>hmsdms = hmsdms.lower()<EOL>hdlist = pattern1.findall(hmsdms)<EOL>parts = [None, None, None]<EOL>def _fill_right_not_none():<EOL><INDENT>rp = reversed(parts)<EOL>for i, j in enumerate(rp):<EOL><INDENT>if j is not None:<EOL><INDENT>break<EOL><DEDENT><DEDENT>if i == <NUM_LIT:0>:<EOL><INDENT>raise ValueError("<STR_LIT>")<EOL><DEDENT>elif i == <NUM_LIT:1>:<EOL><INDENT>parts[<NUM_LIT:2>] = v<EOL><DEDENT>elif i == <NUM_LIT:2>:<EOL><INDENT>if parts[<NUM_LIT:0>] is None:<EOL><INDENT>parts[<NUM_LIT:0>] = v<EOL><DEDENT>else:<EOL><INDENT>parts[<NUM_LIT:1>] = v<EOL><DEDENT><DEDENT><DEDENT>for valun in hdlist:<EOL><INDENT>try:<EOL><INDENT>v = float(valun)<EOL>_fill_right_not_none()<EOL><DEDENT>except ValueError:<EOL><INDENT>if "<STR_LIT>" in valun or "<STR_LIT:h>" in valun:<EOL><INDENT>m = pattern2.search(valun)<EOL>parts[<NUM_LIT:0>] = float(valun[m.start():m.end()])<EOL>units = "<STR_LIT>"<EOL><DEDENT>if "<STR_LIT>" in valun or "<STR_LIT:d>" in valun:<EOL><INDENT>m = pattern2.search(valun)<EOL>parts[<NUM_LIT:0>] = float(valun[m.start():m.end()])<EOL>units = "<STR_LIT>"<EOL><DEDENT>if "<STR_LIT>" in valun or "<STR_LIT:m>" in valun:<EOL><INDENT>m = pattern2.search(valun)<EOL>parts[<NUM_LIT:1>] = float(valun[m.start():m.end()])<EOL><DEDENT>if "<STR_LIT>" in valun or "<STR_LIT:s>" in valun:<EOL><INDENT>m = pattern2.search(valun)<EOL>parts[<NUM_LIT:2>] = float(valun[m.start():m.end()])<EOL><DEDENT>if "<STR_LIT:'>" in valun:<EOL><INDENT>m = pattern2.search(valun)<EOL>parts[<NUM_LIT:1>] = float(valun[m.start():m.end()])<EOL><DEDENT>if '<STR_LIT:">' in valun:<EOL><INDENT>m = pattern2.search(valun)<EOL>parts[<NUM_LIT:2>] = float(valun[m.start():m.end()])<EOL><DEDENT>if "<STR_LIT::>" in valun:<EOL><INDENT>v = valun.replace("<STR_LIT::>", "<STR_LIT>")<EOL>v = float(v)<EOL>_fill_right_not_none()<EOL><DEDENT><DEDENT>if not units:<EOL><INDENT>units = "<STR_LIT>"<EOL><DEDENT><DEDENT>for i in parts:<EOL><INDENT>if i and i < <NUM_LIT:0.0>:<EOL><INDENT>if sign is None:<EOL><INDENT>sign = -<NUM_LIT:1><EOL><DEDENT>else:<EOL><INDENT>raise ValueError("<STR_LIT>")<EOL><DEDENT><DEDENT><DEDENT>if sign is None:  <EOL><INDENT>sign = <NUM_LIT:1><EOL><DEDENT>vals = [abs(i) if i is not None else <NUM_LIT:0.0> for i in parts]<EOL>return dict(sign=sign, units=units, vals=vals, parts=parts)<EOL>
Parse a string containing a sexagesimal number.

    This can handle several types of delimiters and will process
    reasonably valid strings. See examples.

    Parameters
    ----------
    hmsdms : str
        String containing a sexagesimal number.

    Returns
    -------
    d : dict

        parts : a 3 element list of floats
            The three parts of the sexagesimal number that were
            identified.
        vals : 3 element list of floats
            The numerical values of the three parts of the sexagesimal
            number.
        sign : int
            Sign of the sexagesimal number; 1 for positive and -1 for
            negative.
        units : {"degrees", "hours"}
            The units of the sexagesimal number. This is infered from
            the characters present in the string. If it a pure number
            then units is "degrees".

    Examples
    --------
    >>> phmsdms("12") == {
    ... 'parts': [12.0, None, None],
    ... 'sign': 1,
    ... 'units': 'degrees',
    ... 'vals': [12.0, 0.0, 0.0]
    ... }
    True

    >>> phmsdms("12h") == {
    ... 'parts': [12.0, None, None],
    ... 'sign': 1,
    ... 'units': 'hours',
    ... 'vals': [12.0, 0.0, 0.0]
    ... }
    True

    >>> phmsdms("12d13m14.56") == {
    ... 'parts': [12.0, 13.0, 14.56],
    ... 'sign': 1,
    ... 'units': 'degrees',
    ... 'vals': [12.0, 13.0, 14.56]
    ... }
    True

    >>> phmsdms("12d13m14.56") == {
    ... 'parts': [12.0, 13.0, 14.56],
    ... 'sign': 1,
    ... 'units': 'degrees',
    ... 'vals': [12.0, 13.0, 14.56]
    ... }
    True

    >>> phmsdms("12d14.56ss") == {
    ... 'parts': [12.0, None, 14.56],
    ... 'sign': 1,
    ... 'units': 'degrees',
    ... 'vals': [12.0, 0.0, 14.56]
    ... }
    True

    >>> phmsdms("14.56ss") == {
    ... 'parts': [None, None, 14.56],
    ... 'sign': 1,
    ... 'units': 'degrees',
    ... 'vals': [0.0, 0.0, 14.56]
    ... }
    True

    >>> phmsdms("12h13m12.4s") == {
    ... 'parts': [12.0, 13.0, 12.4],
    ... 'sign': 1,
    ... 'units': 'hours',
    ... 'vals': [12.0, 13.0, 12.4]
    ... }
    True

    >>> phmsdms("12:13:12.4s") == {
    ... 'parts': [12.0, 13.0, 12.4],
    ... 'sign': 1,
    ... 'units': 'degrees',
    ...  'vals': [12.0, 13.0, 12.4]
    ... }
    True

    But `phmsdms("12:13mm:12.4s")` will not work.