blob: dd60cf78797b9a4582912df62505a18098b30205 [file] [log] [blame]
# Copyright 2023 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Backports of Python features.
This module serves as a clearing house location for backporting stdlib
functionality to the minimum Python version supported by chromite.
Please use the _available_in decorator on all functions, which will cause
the function to start generating warnings once Chromite's minimum Python
version advances.
"""
import functools
from pathlib import Path
from typing import Any, Callable, Tuple
import warnings
import chromite
def _available_in(
python_version: Tuple[int, int], stdlib_equivalent: str
) -> Callable[[Callable[..., Any]], Callable[..., Any]]:
"""Annotate a function as available in a certain Python version.
Args:
python_version: The first version the functionality is available.
stdlib_equivalent: The name of the standard library equivalent.
Returns:
A function to wrap your function.
"""
def _decorator(f: Callable[..., Any]) -> Callable[..., Any]:
@functools.wraps(f)
def _wrapper(*args: Any, **kwargs: Any) -> Any:
if python_version <= chromite.MIN_PYTHON_VERSION:
warnings.warn(
f"{f.__name__} is now available in the Python standard "
f"library. Please use {stdlib_equivalent} instead.",
DeprecationWarning,
)
return f(*args, **kwargs)
return _wrapper
return _decorator
@_available_in((3, 9), "pathlib.Path.is_relative_to")
def path_is_relative_to(inner: Path, outer: Path) -> bool:
"""Backport of Path.is_relative_to() (available in Python 3.9+).
Args:
inner: The inner path.
outer: The outer path.
Returns:
True if inner is inside the parents of outer, false otherwise.
"""
return outer == inner or outer in inner.parents