Repository: matplotlib/matplotlib
File: lib/matplotlib/colors.py (Python)

Code before:
            # This may turn c into a non-string, so we check again below.
            c = _colors_full_map[c]
        except KeyError:
            if len(c) != 1:
                try:
                    c = _colors_full_map[c.lower()]
                except KeyError:
                    pass
    if isinstance(c, str):
        if re.match(r"\A#[a-fA-F0-9]+\Z", c):
            if len(c) == 7:  # #rrggbb hex format.
                return (*[n / 0xff for n in bytes.fromhex(c[1:])],
                        alpha if alpha is not None else 1.)
            elif len(c) == 4:  # #rgb hex format, shorthand for #rrggbb.
                return (*[int(n, 16) * 0x11 / 0xff for n in c[1:]],
                        alpha if alpha is not None else 1.)
            elif len(c) == 9:  # #rrggbbaa hex format.
                color = [n / 0xff for n in bytes.fromhex(c[1:])]
                if alpha is not None:
                    color[-1] = alpha
                return tuple(color)
            elif len(c) == 5:  # #rgba hex format, shorthand for #rrggbbaa.
                color = [int(n, 16) * 0x11 / 0xff for n in c[1:]]
                if alpha is not None:
                    color[-1] = alpha
                return tuple(color)
        # string gray.
        try:
            c = float(c)
        except ValueError:
            pass
        else:
            if not (0 <= c <= 1):
                raise ValueError(
                    f"Invalid string grayscale value {orig_c!r}. "
                    f"Value must be within 0-1 range")
            return c, c, c, alpha if alpha is not None else 1.
        raise ValueError(f"Invalid RGBA argument: {orig_c!r}")
    # turn 2-D array into 1-D array
    if isinstance(c, np.ndarray):
        if c.ndim == 2 and c.shape[0] == 1:
            c = c.reshape(-1)
    # tuple color.
    if not np.iterable(c):
        raise ValueError(f"Invalid RGBA argument: {orig_c!r}")
    if len(c) not in [3, 4]:
        raise ValueError("RGBA sequence should have length 3 or 4")
    if not all(isinstance(x, Real) for x in c):
        # Checks that don't work: `map(float, ...)`, `np.array(..., float)` and
        # `np.array(...).astype(float)` would all convert "0.5" to 0.5.
        raise ValueError(f"Invalid RGBA argument: {orig_c!r}")

Review comment (suggestion):
```suggestion
                return tuple(color)
            else:
                raise ValueError(f"{orig_c!r} is not a valid hex color specifier")
```

Code after:
            # This may turn c into a non-string, so we check again below.
            c = _colors_full_map[c]
        except KeyError:
            if len(c) != 1:
                try:
                    c = _colors_full_map[c.lower()]
                except KeyError:
                    pass
    if isinstance(c, str):
        if re.fullmatch("#[a-fA-F0-9]+", c):
            if len(c) == 7:  # #rrggbb hex format.
                return (*[n / 0xff for n in bytes.fromhex(c[1:])],
                        alpha if alpha is not None else 1.)
            elif len(c) == 4:  # #rgb hex format, shorthand for #rrggbb.
                return (*[int(n, 16) / 0xf for n in c[1:]],
                        alpha if alpha is not None else 1.)
            elif len(c) == 9:  # #rrggbbaa hex format.
                color = [n / 0xff for n in bytes.fromhex(c[1:])]
                if alpha is not None:
                    color[-1] = alpha
                return tuple(color)
            elif len(c) == 5:  # #rgba hex format, shorthand for #rrggbbaa.
                color = [int(n, 16) / 0xf for n in c[1:]]
                if alpha is not None:
                    color[-1] = alpha
                return tuple(color)
            else:
                raise ValueError(f"Invalid hex color specifier: {orig_c!r}")
        # string gray.
        try:
            c = float(c)
        except ValueError:
            pass
        else:
            if not (0 <= c <= 1):
                raise ValueError(
                    f"Invalid string grayscale value {orig_c!r}. "
                    f"Value must be within 0-1 range")
            return c, c, c, alpha if alpha is not None else 1.
        raise ValueError(f"Invalid RGBA argument: {orig_c!r}")
    # turn 2-D array into 1-D array
    if isinstance(c, np.ndarray):
        if c.ndim == 2 and c.shape[0] == 1:
            c = c.reshape(-1)
    # tuple color.
    if not np.iterable(c):
        raise ValueError(f"Invalid RGBA argument: {orig_c!r}")
    if len(c) not in [3, 4]:
        raise ValueError("RGBA sequence should have length 3 or 4")
    if not all(isinstance(x, Real) for x in c):
        # Checks that don't work: `map(float, ...)`, `np.array(..., float)` and