| 1234567891011121314151617181920212223242526272829303132333435363738394041 |
- """Utilities for working with paths."""
- from collections.abc import Sequence
- from contextlib import suppress
- def normalize_path_segments(segments: Sequence[str]) -> list[str]:
- """Drop '.' and '..' from a sequence of str segments"""
- resolved_path: list[str] = []
- for seg in segments:
- if seg == "..":
- # ignore any .. segments that would otherwise cause an
- # IndexError when popped from resolved_path if
- # resolving for rfc3986
- with suppress(IndexError):
- resolved_path.pop()
- elif seg != ".":
- resolved_path.append(seg)
- if segments and segments[-1] in (".", ".."):
- # do some post-processing here.
- # if the last segment was a relative dir,
- # then we need to append the trailing '/'
- resolved_path.append("")
- return resolved_path
- def normalize_path(path: str) -> str:
- # Drop '.' and '..' from str path
- prefix = ""
- if path and path[0] == "/":
- # preserve the "/" root element of absolute paths, copying it to the
- # normalised output as per sections 5.2.4 and 6.2.2.3 of rfc3986.
- prefix = "/"
- path = path[1:]
- segments = path.split("/")
- return prefix + "/".join(normalize_path_segments(segments))
|