From ebb65f0b9d445b9b54168dfdba60bee6e8c27c20 Mon Sep 17 00:00:00 2001 From: p1c2u Date: Wed, 18 Feb 2026 18:13:47 +0000 Subject: [PATCH] Optimize parse parts --- pathable/parsers.py | 41 +++++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/pathable/parsers.py b/pathable/parsers.py index 1aa5102..9960c5f 100644 --- a/pathable/parsers.py +++ b/pathable/parsers.py @@ -10,39 +10,48 @@ def parse_parts( parts: Sequence[Hashable | None], sep: str = SEPARATOR ) -> list[Hashable]: """Parse (filter and split) path parts.""" - - def append_split(part: str) -> None: - if not part or part == ".": - return - if sep_check in part: - for split_part in reversed(part.split(sep_check)): - if split_part and split_part != ".": - append(split_part) - return - append(part) - parsed: list[Hashable] = [] append = parsed.append - sep_check = sep - for part in reversed(parts): + + for part in parts: if part is None: continue + # Fast-path: int is common and never needs splitting/decoding. if isinstance(part, int): append(part) continue + # Fast-path: str is most common. if isinstance(part, str): - append_split(part) + if not part or part == ".": + continue + if sep in part: + for split_part in part.split(sep): + if split_part and split_part != ".": + append(split_part) + continue + append(part) continue + # Fast-path: bytes, decode then treat as str. if isinstance(part, bytes): - append_split(part.decode("ascii")) + text = part.decode("ascii") + if not text or text == ".": + continue + if sep in text: + for split_part in text.split(sep): + if split_part and split_part != ".": + append(split_part) + continue + append(text) continue + # Fallback: Hashable (covers e.g. tuple, custom keys). if isinstance(part, Hashable): append(part) continue + raise TypeError(f"part must be Hashable or None; got {type(part)!r}") - parsed.reverse() + return parsed