48 lines
1.8 KiB
Python
48 lines
1.8 KiB
Python
"""Compatibility functions to support wider version ranges for python and dependencies."""
|
|
|
|
# Copyright (c) Microsoft Corporation.
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
|
|
# DeepSpeed Team
|
|
|
|
from typing import Mapping, Any, Dict
|
|
from inspect import ismodule
|
|
try:
|
|
import annotationlib # python >= 3.14
|
|
except ImportError:
|
|
annotationlib = None
|
|
|
|
# Deal with annotations in python versions >=3.14. See:
|
|
# - Python 3.14 release notes: https://docs.python.org/3/whatsnew/3.14.html
|
|
# Porting annotations: https://docs.python.org/3/whatsnew/3.14.html#whatsnew314-porting-annotations
|
|
# - PEP649: https://peps.python.org/pep-0649/
|
|
# - PEP749: https://peps.python.org/pep-0749/
|
|
# Backwards compatible, applies best practices (use annotationlib) from python 3.14 onwards.
|
|
|
|
|
|
def get_annotations_from_namespace(namespace: Mapping[str, object]) -> Dict[str, Any]:
|
|
if annotationlib:
|
|
annotate_func = annotationlib.get_annotate_from_class_namespace(namespace)
|
|
if annotate_func is not None:
|
|
return annotationlib.call_annotate_function(annotate_func, annotationlib.Format.VALUE)
|
|
return namespace.get("__annotations__", {})
|
|
|
|
|
|
def get_annotations(obj: Any) -> Dict[str, Any]:
|
|
"""
|
|
Retrieves annotations from a Python object.
|
|
|
|
In python >=3.14 this is a thin wrapper around the `annotationlib.get_annotations` function
|
|
with the added convenience to automatically infer the type for non module, class, function
|
|
or customly annotated objects.
|
|
"""
|
|
if annotationlib:
|
|
has_annotations = hasattr(obj, "__annotations__") or hasattr(obj, "__annotate__")
|
|
if not isinstance(obj, type) and not ismodule(obj) and not callable(obj) and not has_annotations:
|
|
obj = type(obj)
|
|
return annotationlib.get_annotations(obj)
|
|
try:
|
|
return obj.__annotations__
|
|
except AttributeError:
|
|
return {}
|