I'd be more inclined to tighten up the check for the "can't mix" message to something like:
valid_types = all(isinstance(s, (str, bytes, bytearray)) for s in (a, ) + p)
if valid_types:
# Must have a mixture of text and binary data
raise TypeError("Can't mix strings and bytes in path components.")
raise
If people pass in something that isn't a valid argument *at all*, then I'm fine with just letting the underlying exception pass through.
The str/bytes case is just worth special-casing because either on their own *are* valid arguments.