blob: 6b8e1b784016a94fde7b78418bc251f21ed7f038 [file] [log] [blame]
# Copyright 2024 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import pathlib
import re
import unicodedata
from typing import Optional, Union
# A path that can refer to files on a remote platform with potentially
# a different Path flavour (e.g. Win vs Posix).
AnyPath = pathlib.PurePath
AnyPosixPath = pathlib.PurePosixPath
AnyWindowsPath = pathlib.PureWindowsPath
AnyPathLike = Union[str, AnyPath]
# A path that only ever refers to files on the local host / runner platform.
# Not that Path inherits from PurePath, and thus we can use a LocalPath in
# all places a RemotePath is expected.
LocalPath = pathlib.Path
LocalPosixPath = pathlib.PosixPath
LocalPathLike = Union[str, LocalPath]
_UNSAFE_FILENAME_CHARS_RE = re.compile(r"[^a-zA-Z0-9+\-_.]")
def safe_filename(name: str) -> str:
normalized_name = unicodedata.normalize("NFKD", name)
ascii_name = normalized_name.encode("ascii", "ignore").decode("ascii")
return _UNSAFE_FILENAME_CHARS_RE.sub("_", ascii_name)
def try_resolve_existing_path(value: str) -> Optional[LocalPath]:
if not value:
return None
maybe_path = LocalPath(value)
if maybe_path.exists():
return maybe_path
maybe_path = maybe_path.expanduser()
if maybe_path.exists():
return maybe_path
return None